summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwushin <pasekei@gmail.com>2015-06-08 00:40:20 -0500
committermekolat <mekolat@users.noreply.github.com>2016-04-15 11:44:40 -0400
commit8ac49c6058db5bf7f06662b8370b1d0fdf17d578 (patch)
tree8e992ce93451edaab463bc0d145028b0d31c4a95
parentc3e06ffe6437d27a2a7c6ddb2dc487ff2f007adf (diff)
downloadtmwa-8ac49c6058db5bf7f06662b8370b1d0fdf17d578.tar.gz
tmwa-8ac49c6058db5bf7f06662b8370b1d0fdf17d578.tar.bz2
tmwa-8ac49c6058db5bf7f06662b8370b1d0fdf17d578.tar.xz
tmwa-8ac49c6058db5bf7f06662b8370b1d0fdf17d578.zip
new/modified builtins
areatimer foreach aggravate Override attack animation injure summon
-rw-r--r--src/map/map.hpp4
-rw-r--r--src/map/mob.cpp10
-rw-r--r--src/map/mob.hpp1
-rw-r--r--src/map/npc.cpp88
-rw-r--r--src/map/npc.hpp1
-rw-r--r--src/map/pc.cpp67
-rw-r--r--src/map/pc.hpp2
-rw-r--r--src/map/script-fun.cpp329
8 files changed, 484 insertions, 18 deletions
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 47eef57..a2f2ff2 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -208,6 +208,7 @@ struct map_session_data : block_list, SessionData
tick_t cast_tick; // [Fate] Next tick at which spellcasting is allowed
dumb_ptr<magic::invocation> active_spells; // [Fate] Singly-linked list of active spells linked to this PC
BlockId attack_spell_override; // [Fate] When an attack spell is active for this player, they trigger it
+ NpcEvent magic_attack;
// like a weapon. Check pc_attack_timer() for details.
// Weapon equipment slot (slot 4) item override
StatusChange attack_spell_icon_override;
@@ -479,6 +480,9 @@ struct mob_data : block_list
// [Fate] mob-specific stats
earray<unsigned short, mob_stat, mob_stat::LAST> stats;
short size;
+ // Npc Runscripts
+ std::list<RString> eventqueuel;
+ Array<Timer, MAX_EVENTTIMER> eventtimer;
};
struct BlockLists
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 7566e03..1be40f0 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -1396,6 +1396,16 @@ int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist)
return 0;
}
+int mob_aggravate(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl)
+{
+ if (md->bl_type != BL::MOB)
+ return 0;
+ mob_target(md, bl, battle_get_range(bl));
+ md->target_id = bl->bl_id;
+ md->attacked_id = bl->bl_id;
+ return 1;
+}
+
/*==========================================
* The ?? routine of an active monster
*------------------------------------------
diff --git a/src/map/mob.hpp b/src/map/mob.hpp
index 6d87228..a466d0b 100644
--- a/src/map/mob.hpp
+++ b/src/map/mob.hpp
@@ -100,6 +100,7 @@ BlockId mob_once_spawn_area(dumb_ptr<map_session_data> sd,
NpcEvent event);
int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist);
+int mob_aggravate(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl);
int mob_stop_walking(dumb_ptr<mob_data> md, int type);
int mob_stopattack(dumb_ptr<mob_data>);
int mob_spawn(BlockId);
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index 4296432..1707c1c 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -286,6 +286,94 @@ int npc_event_do_oninit(void)
return 0;
}
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static
+void npc_eventtimer(TimerData *, tick_t, BlockId id, NpcEvent data)
+{
+ Option<P<struct event_data>> ev_ = ev_db.search(data);
+ dumb_ptr<npc_data_script> nd;
+ dumb_ptr<block_list> bl = map_id2bl(id);
+
+ if (ev_.is_none() && data.label == stringish<ScriptLabel>("OnTouch"_s))
+ return;
+
+ P<struct event_data> ev = TRY_UNWRAP(ev_,
+ {
+ if (battle_config.error_log)
+ PRINTF("npc_event: event not found [%s]\n"_fmt,
+ data);
+ return;
+ });
+ if ((nd = ev->nd) == nullptr)
+ {
+ if (battle_config.error_log)
+ PRINTF("npc_event: event not found [%s]\n"_fmt,
+ data);
+ return;
+ }
+
+ if (nd->scr.event_needs_map)
+ {
+ int xs = nd->scr.xs;
+ int ys = nd->scr.ys;
+ if (nd->bl_m != bl->bl_m)
+ return;
+ if (xs > 0
+ && (bl->bl_x < nd->bl_x - xs / 2 || nd->bl_x + xs / 2 < bl->bl_x))
+ return;
+ if (ys > 0
+ && (bl->bl_y < nd->bl_y - ys / 2 || nd->bl_y + ys / 2 < bl->bl_y))
+ return;
+ }
+
+ run_script(ScriptPointer(borrow(*nd->scr.script), ev->pos), id, nd->bl_id);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_addeventtimer(dumb_ptr<block_list> bl, interval_t tick, NpcEvent name)
+{
+ int i;
+
+ nullpo_retz(bl);
+ if (bl->bl_type == BL::MOB)
+ {
+ dumb_ptr<mob_data> md = bl->is_mob();
+ for (i = 0; i < MAX_EVENTTIMER; i++)
+ if (!md->eventtimer[i])
+ break;
+
+ if (i < MAX_EVENTTIMER)
+ {
+ md->eventtimer[i] = Timer(gettick() + tick,
+ std::bind(npc_eventtimer, ph::_1, ph::_2,
+ md->bl_id, name));
+ return 1;
+ }
+ }
+ if (bl->bl_type == BL::NPC)
+ {
+ dumb_ptr<npc_data> nd = bl->is_npc();
+ for (i = 0; i < MAX_EVENTTIMER; i++)
+ if (!nd->eventtimer[i])
+ break;
+
+ if (i < MAX_EVENTTIMER)
+ {
+ nd->eventtimer[i] = Timer(gettick() + tick,
+ std::bind(npc_eventtimer, ph::_1, ph::_2,
+ nd->bl_id, name));
+ return 1;
+ }
+ }
+ return 0;
+}
+
/// Callback for npc OnTimer*: labels.
/// This will be called later if you call npc_timerevent_start.
/// This function may only expire, but not deactivate, the counter.
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index b587f5f..7a96bf9 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -45,6 +45,7 @@ constexpr Species INVISIBLE_CLASS = wrap<Species>(32767);
int npc_event_dequeue(dumb_ptr<map_session_data> sd);
int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int);
+int npc_addeventtimer(dumb_ptr<block_list> bl, interval_t tick, NpcEvent name);
int npc_touch_areanpc(dumb_ptr<map_session_data>, Borrowed<map_local>, int, int);
int npc_click(dumb_ptr<map_session_data>, BlockId);
int npc_scriptcont(dumb_ptr<map_session_data>, BlockId);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index c47925f..c4c3ad9 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -635,6 +635,51 @@ int pc_isequip(dumb_ptr<map_session_data> sd, IOff0 n)
return 1;
}
+void pc_set_weapon_icon(dumb_ptr<map_session_data> sd, int count,
+ StatusChange icon, ItemNameId look)
+{
+ const StatusChange old_icon = sd->attack_spell_icon_override;
+
+ sd->attack_spell_icon_override = icon;
+ sd->attack_spell_look_override = look;
+
+ if (old_icon != StatusChange::ZERO && old_icon != icon)
+ clif_status_change(sd, old_icon, 0);
+
+ clif_fixpcpos(sd);
+ if (count)
+ {
+ clif_changelook(sd, LOOK::WEAPON, unwrap<ItemNameId>(look));
+ if (icon != StatusChange::ZERO)
+ clif_status_change(sd, icon, 1);
+ }
+ else
+ {
+ /* Set it to `normal' */
+ clif_changelook(sd, LOOK::WEAPON,
+ static_cast<uint16_t>(sd->status.weapon));
+ }
+}
+
+void pc_set_attack_info(dumb_ptr<map_session_data> sd, interval_t speed, int range)
+{
+ sd->attack_spell_delay = speed;
+ sd->attack_spell_range = range;
+
+ if (speed == interval_t::zero())
+ {
+ pc_calcstatus(sd, 1);
+ clif_updatestatus(sd, SP::ASPD);
+ clif_updatestatus(sd, SP::ATTACKRANGE);
+ }
+ else
+ {
+ sd->aspd = speed;
+ clif_updatestatus(sd, SP::ASPD);
+ clif_updatestatus(sd, SP::ATTACKRANGE);
+ }
+}
+
/*==========================================
* session idに問題無し
* char鯖から送られてきたステータスを設定
@@ -2608,13 +2653,23 @@ void pc_attack_timer(TimerData *, tick_t tick, BlockId id)
if (sd->attackabletime > tick)
return; // cannot attack yet
- interval_t attack_spell_delay = sd->attack_spell_delay;
- if (sd->attack_spell_override // [Fate] If we have an active attack spell, use that
- && magic::spell_attack(id, sd->attacktarget))
+ if (sd->attack_spell_override) // [Fate] If we have an active attack spell, use that
{
- // Return if the spell succeeded. If the spell had disspiated, spell_attack() may fail.
- sd->attackabletime = tick + attack_spell_delay;
-
+ // call_spell_event_script
+ argrec_t arg[1] =
+ {
+ {"@target_id"_s, static_cast<int32_t>(unwrap<BlockId>(bl->bl_id))},
+ };
+ npc_event_do_l(sd->magic_attack, sd->bl_id, arg);
+ sd->attackabletime = tick + sd->attack_spell_delay;
+ sd->attack_spell_charges--;
+ if (!sd->attack_spell_charges)
+ {
+ sd->attack_spell_override = BlockId();
+ pc_set_weapon_icon(sd, 0, StatusChange::ZERO, ItemNameId());
+ pc_set_attack_info(sd, interval_t::zero(), 0);
+ pc_calcstatus(sd, 0);
+ }
}
else
{
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index db1d5be..3a35330 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -80,6 +80,8 @@ int pc_counttargeted(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> src,
int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type);
void pc_makesavestatus(dumb_ptr<map_session_data>);
int pc_setnewpc(dumb_ptr<map_session_data>, AccountId, CharId, int, uint32_t /*tick_t*/, SEX);
+void pc_set_weapon_icon(dumb_ptr<map_session_data> sd, int count,StatusChange icon, ItemNameId look);
+void pc_set_attack_info(dumb_ptr<map_session_data> sd, interval_t speed, int range);
int pc_authok(AccountId, int, ClientVersion, const CharKey *, const CharData *);
int pc_authfail(AccountId accid);
diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp
index 07076d5..9f9652e 100644
--- a/src/map/script-fun.cpp
+++ b/src/map/script-fun.cpp
@@ -70,6 +70,13 @@ namespace map
#define AARG(n) (st->stack->stack_datav[st->start + 2 + (n)])
#define HARG(n) (st->end > st->start + 2 + (n))
+enum class MonsterAttitude
+{
+ HOSTILE = 0,
+ FRIENDLY = 1,
+ SERVANT = 2,
+ FROZEN = 3,
+};
//
// 埋め込み関数
//
@@ -503,6 +510,81 @@ void builtin_heal(ScriptState *st)
*------------------------------------------
*/
static
+void builtin_elttype(ScriptState *st)
+{
+ int element_type = static_cast<int>(battle_get_element(map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))))).element);
+ push_int<ScriptDataInt>(st->stack, element_type);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static
+void builtin_eltlvl(ScriptState *st)
+{
+ int element_lvl = static_cast<int>(battle_get_element(map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))))).level);
+ push_int<ScriptDataInt>(st->stack, element_lvl);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static
+void builtin_injure(ScriptState *st)
+{
+ dumb_ptr<block_list> caster = map_id2bl(st->rid);
+ dumb_ptr<block_list> target = map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))));
+ int damage_caused = conv_num(st, &AARG(1));
+ int mp_damage = conv_num(st, &AARG(2));
+ int target_hp = battle_get_hp(target);
+ int mdef = battle_get_mdef(target);
+
+ if (target->bl_type == BL::PC
+ && !target->bl_m->flag.get(MapFlag::PVP)
+ && (caster->bl_type == BL::PC)
+ && ((caster->is_player()->state.pvpchannel > 1) && (target->is_player()->state.pvpchannel != caster->is_player()->state.pvpchannel)))
+ return; /* Cannot damage other players outside of pvp */
+
+ if (target != caster)
+ {
+ /* Not protected against own spells */
+ damage_caused = (damage_caused * (100 - mdef)) / 100;
+ mp_damage = (mp_damage * (100 - mdef)) / 100;
+ }
+
+ damage_caused = (damage_caused > target_hp) ? target_hp : damage_caused;
+
+ if (damage_caused < 0)
+ damage_caused = 0;
+
+ // display damage first, because dealing damage may deallocate the target.
+ clif_damage(caster, target,
+ gettick(), interval_t::zero(), interval_t::zero(),
+ damage_caused, 0, DamageType::NORMAL);
+
+ if (caster->bl_type == BL::PC)
+ {
+ dumb_ptr<map_session_data> caster_pc = caster->is_player();
+ if (target->bl_type == BL::MOB)
+ {
+ dumb_ptr<mob_data> mob = target->is_mob();
+ dumb_ptr<npc_data> nd = map_id_is_npc(st->oid);
+ MAP_LOG_PC(caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s"_fmt,
+ mob->bl_id, mob->mob_class, damage_caused, nd->name);
+ }
+ }
+ battle_damage(caster, target, damage_caused, mp_damage);
+
+ return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static
void builtin_input(ScriptState *st)
{
dumb_ptr<map_session_data> sd = nullptr;
@@ -640,6 +722,61 @@ void builtin_elif (ScriptState *st)
}
/*==========================================
+ *
+ *------------------------------------------
+ */
+static
+void builtin_foreach_sub(dumb_ptr<block_list> bl, NpcEvent event, BlockId caster)
+{
+ // call_spell_event_script
+ argrec_t arg[1] =
+ {
+ {"@target_id"_s, static_cast<int32_t>(unwrap<BlockId>(bl->bl_id))},
+ };
+ npc_event_do_l(event, caster, arg);
+}
+static
+void builtin_foreach(ScriptState *st)
+{
+ int x0, y0, x1, y1, bl_num;
+
+ dumb_ptr<block_list> caster = map_id2bl(st->rid);
+ bl_num = conv_num(st, &AARG(0));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(1))));
+ x0 = conv_num(st, &AARG(2));
+ y0 = conv_num(st, &AARG(3));
+ x1 = conv_num(st, &AARG(4));
+ y1 = conv_num(st, &AARG(5));
+ ZString event_ = ZString(conv_str(st, &AARG(6)));
+ BL block_type;
+ NpcEvent event;
+ extract(event_, &event);
+
+ P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return);
+
+ switch (bl_num)
+ {
+ case 0:
+ block_type = BL::PC;
+ break;
+ case 1:
+ block_type = BL::NPC;
+ break;
+ case 2:
+ block_type = BL::MOB;
+ break;
+ default:
+ return;
+ }
+
+ map_foreachinarea(std::bind(builtin_foreach_sub, ph::_1, event, caster->bl_id),
+ m,
+ x0, y0,
+ x1, y1,
+ block_type);
+}
+
+/*==========================================
* 変数設定
*------------------------------------------
*/
@@ -1401,6 +1538,31 @@ void builtin_getskilllv(ScriptState *st)
*------------------------------------------
*/
static
+void builtin_overrideattack(ScriptState *st)
+{
+ dumb_ptr<map_session_data> sd = script_rid2sd(st);
+ int charges = conv_num(st, &AARG(0));
+ interval_t attack_delay = static_cast<interval_t>(conv_num(st, &AARG(1)));
+ int attack_range = conv_num(st, &AARG(2));
+ StatusChange icon = StatusChange(conv_num(st, &AARG(3)));
+ ItemNameId look = wrap<ItemNameId>(static_cast<uint16_t>(conv_num(st, &AARG(4))));
+ ZString event_ = ZString(conv_str(st, &AARG(5)));
+
+ NpcEvent event;
+ extract(event_, &event);
+
+ sd->attack_spell_override = st->oid;
+ sd->attack_spell_charges = charges;
+ sd->magic_attack = event;
+ pc_set_weapon_icon(sd, charges, icon, look);
+ pc_set_attack_info(sd, attack_delay, attack_range);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static
void builtin_getgmlevel(ScriptState *st)
{
push_int<ScriptDataInt>(st->stack, pc_isGM(script_rid2sd(st)).get_all_bits());
@@ -1594,6 +1756,72 @@ void builtin_getexp(ScriptState *st)
}
+static
+void builtin_summon(ScriptState *st)
+{
+ NpcEvent event;
+ MapName map = stringish<MapName>(ZString(conv_str(st, &AARG(0))));
+ int x = conv_num(st, &AARG(1));
+ int y = conv_num(st, &AARG(2));
+ dumb_ptr<block_list> owner_e = map_id2bl(wrap<BlockId>(conv_num(st, &AARG(3))));
+ dumb_ptr<map_session_data> owner = nullptr;
+ Species monster_id = wrap<Species>(conv_num(st, &AARG(4)));
+ MonsterAttitude monster_attitude = static_cast<MonsterAttitude>(conv_num(st, &AARG(5)));
+ interval_t lifespan = static_cast<interval_t>(conv_num(st, &AARG(6)));
+ if (HARG(7))
+ extract(ZString(conv_str(st, &AARG(7))), &event);
+
+ if (monster_attitude == MonsterAttitude::SERVANT
+ && owner_e->bl_type == BL::PC)
+ owner = owner_e->is_player(); // XXX in the future this should also work with mobs as owner
+
+ BlockId mob_id = mob_once_spawn(owner, map, x, y, MobName(), monster_id, 1, event);
+ dumb_ptr<mob_data> mob = map_id_is_mob(mob_id);
+
+ if (mob)
+ {
+ mob->mode = get_mob_db(monster_id).mode;
+
+ switch (monster_attitude)
+ {
+ case MonsterAttitude::SERVANT:
+ mob->state.special_mob_ai = 1;
+ mob->mode |= MobMode::AGGRESSIVE;
+ break;
+
+ case MonsterAttitude::FRIENDLY:
+ mob->mode = MobMode::CAN_ATTACK | (mob->mode & MobMode::CAN_MOVE);
+ break;
+
+ case MonsterAttitude::HOSTILE:
+ mob->mode = MobMode::CAN_ATTACK | MobMode::AGGRESSIVE | (mob->mode & MobMode::CAN_MOVE);
+ if (owner)
+ {
+ mob->target_id = owner->bl_id;
+ mob->attacked_id = owner->bl_id;
+ }
+ break;
+
+ case MonsterAttitude::FROZEN:
+ mob->mode = MobMode::ZERO;
+ break;
+ }
+
+ mob->mode |=
+ MobMode::SUMMONED | MobMode::TURNS_AGAINST_BAD_MASTER;
+
+ mob->deletetimer = Timer(gettick() + lifespan,
+ std::bind(mob_timer_delete, ph::_1, ph::_2,
+ mob_id));
+
+ if (owner)
+ {
+ mob->master_id = owner->bl_id;
+ mob->master_dist = 6;
+ }
+ }
+}
+
/*==========================================
* モンスター発生
*------------------------------------------
@@ -1981,6 +2209,38 @@ void builtin_getmapusers(ScriptState *st)
push_int<ScriptDataInt>(st->stack, users);
}
+static
+void builtin_aggravate_sub(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int effect)
+{
+ dumb_ptr<mob_data> md = bl->is_mob();
+
+ if (mob_aggravate(md, target))
+ clif_misceffect(bl, effect);
+}
+
+static
+void builtin_aggravate(ScriptState *st)
+{
+ dumb_ptr<block_list> target = map_id2bl(st->rid);
+ MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0))));
+ int x0 = conv_num(st, &AARG(1));
+ int y0 = conv_num(st, &AARG(2));
+ int x1 = conv_num(st, &AARG(3));
+ int y1 = conv_num(st, &AARG(4));
+ int effect = conv_num(st, &AARG(5));
+ P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str),
+ {
+ push_int<ScriptDataInt>(st->stack, -1);
+ return;
+ });
+
+ map_foreachinarea(std::bind(builtin_aggravate_sub, ph::_1, target, effect),
+ m,
+ x0, y0,
+ x1, y1,
+ BL::MOB);
+}
+
/*==========================================
* エリア指定ユーザー数所得
*------------------------------------------
@@ -3069,6 +3329,18 @@ void builtin_npctalk(ScriptState *st)
}
/*==========================================
+ * casttime
+ *------------------------------------------
+ */
+static
+void builtin_casttime(ScriptState *st)
+{
+ dumb_ptr<map_session_data> sd = script_rid2sd(st);
+ interval_t tick = static_cast<interval_t>(conv_num(st, &AARG(0)));
+ sd->cast_tick = gettick() + tick;
+}
+
+/*==========================================
* getlook char info. getlook(arg)
*------------------------------------------
*/
@@ -3152,31 +3424,56 @@ void builtin_getsavepoint(ScriptState *st)
static
void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, NpcEvent event)
{
- pc_addeventtimer(bl->is_player(), tick, event);
+ if (bl->bl_type == BL::PC)
+ {
+ dumb_ptr<map_session_data> sd = map_id_is_player(bl->bl_id);
+ pc_addeventtimer(sd, tick, event);
+ }
+ else
+ {
+ npc_addeventtimer(bl, tick, event);
+ }
}
static
void builtin_areatimer(ScriptState *st)
{
- int x0, y0, x1, y1;
-
- MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0))));
- x0 = conv_num(st, &AARG(1));
- y0 = conv_num(st, &AARG(2));
- x1 = conv_num(st, &AARG(3));
- y1 = conv_num(st, &AARG(4));
- interval_t tick = static_cast<interval_t>(conv_num(st, &AARG(5)));
- ZString event_ = ZString(conv_str(st, &AARG(6)));
+ int x0, y0, x1, y1, bl_num;
+
+ bl_num = conv_num(st, &AARG(0));
+ MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(1))));
+ x0 = conv_num(st, &AARG(2));
+ y0 = conv_num(st, &AARG(3));
+ x1 = conv_num(st, &AARG(4));
+ y1 = conv_num(st, &AARG(5));
+ interval_t tick = static_cast<interval_t>(conv_num(st, &AARG(6)));
+ ZString event_ = conv_str(st, &AARG(7));
+ BL block_type;
NpcEvent event;
extract(event_, &event);
P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return);
+ switch (bl_num)
+ {
+ case 0:
+ block_type = BL::PC;
+ break;
+ case 1:
+ block_type = BL::NPC;
+ break;
+ case 2:
+ block_type = BL::MOB;
+ break;
+ default:
+ return;
+ }
+
map_foreachinarea(std::bind(builtin_areatimer_sub, ph::_1, tick, event),
m,
x0, y0,
x1, y1,
- BL::PC);
+ block_type);
}
/*==========================================
@@ -3431,6 +3728,9 @@ BuiltinFunction builtin_functions[] =
BUILTIN(warp, "Mxy"_s, '\0'),
BUILTIN(areawarp, "MxyxyMxy"_s, '\0'),
BUILTIN(heal, "ii?"_s, '\0'),
+ BUILTIN(elttype, "i"_s, 'i'),
+ BUILTIN(eltlvl, "i"_s, 'i'),
+ BUILTIN(injure, "iii"_s, '\0'),
BUILTIN(input, "N"_s, '\0'),
BUILTIN(if, "iF*"_s, '\0'),
BUILTIN(elif, "iF*"_s, '\0'),
@@ -3456,6 +3756,7 @@ BuiltinFunction builtin_functions[] =
BUILTIN(skill, "ii?"_s, '\0'),
BUILTIN(setskill, "ii"_s, '\0'),
BUILTIN(getskilllv, "i"_s, 'i'),
+ BUILTIN(overrideattack, "iiiiiE"_s, '\0'),
BUILTIN(getgmlevel, ""_s, 'i'),
BUILTIN(end, ""_s, '\0'),
BUILTIN(getopt2, ""_s, 'i'),
@@ -3465,6 +3766,7 @@ BuiltinFunction builtin_functions[] =
BUILTIN(gettime, "i"_s, 'i'),
BUILTIN(openstorage, ""_s, '\0'),
BUILTIN(getexp, "ii"_s, '\0'),
+ BUILTIN(summon, "Mxysmii?"_s, '\0'),
BUILTIN(monster, "Mxysmi?"_s, '\0'),
BUILTIN(areamonster, "Mxyxysmi?"_s, '\0'),
BUILTIN(killmonster, "ME"_s, '\0'),
@@ -3525,6 +3827,7 @@ BuiltinFunction builtin_functions[] =
BUILTIN(npcareawarp, "xyxyis"_s, '\0'),
BUILTIN(message, "Ps"_s, '\0'),
BUILTIN(npctalk, "ss?"_s, '\0'),
+ BUILTIN(casttime, "i"_s, '\0'),
BUILTIN(title, "s"_s, '\0'),
BUILTIN(smsg, "e??"_s, '\0'),
BUILTIN(remotecmd, "s?"_s, '\0'),
@@ -3533,11 +3836,13 @@ BuiltinFunction builtin_functions[] =
BUILTIN(getmask, ""_s, 'i'),
BUILTIN(getlook, "i"_s, 'i'),
BUILTIN(getsavepoint, "i"_s, '.'),
- BUILTIN(areatimer, "MxyxytE"_s, '\0'),
+ BUILTIN(areatimer, "MxyxytEi"_s, '\0'),
+ BUILTIN(foreach, "iMxyxyE"_s, '\0'),
BUILTIN(isin, "Mxyxy"_s, 'i'),
BUILTIN(iscollision, "Mxy"_s, 'i'),
BUILTIN(shop, "s"_s, '\0'),
BUILTIN(isdead, ""_s, 'i'),
+ BUILTIN(aggravate, "Mxyxyi"_s, '\0'),
BUILTIN(fakenpcname, "ssi"_s, '\0'),
BUILTIN(getx, ""_s, 'i'),
BUILTIN(gety, ""_s, 'i'),