dumb_ptr<invocation> spell_instantiate(effect_set_t *effect_set, dumb_ptr<env_t> env) { dumb_ptr<invocation> retval; retval.new_(); dumb_ptr<block_list> caster; retval->env = env; retval->caster = env->VAR(VAR_CASTER).v.v_int; retval->spell = env->VAR(VAR_SPELL).v.v_spell; retval->stack_size = 0; retval->current_effect = effect_set->effect; retval->trigger_effect = effect_set->at_trigger; retval->end_effect = effect_set->at_end; caster = map_id2bl(retval->caster); // must still exist retval->bl_id = map_addobject(retval); retval->bl_type = BL::SPELL; retval->bl_m = caster->bl_m; retval->bl_x = caster->bl_x; retval->bl_y = caster->bl_y; map_addblock(retval); set_env_invocation(VAR_INVOCATION, retval); return retval; }
static int spellguard_can_satisfy(spellguard_check_t *check, dumb_ptr<map_session_data> caster, dumb_ptr<env_t> env, int *near_miss) { tick_t tick = gettick(); int retval = check_prerequisites(caster, check->catalysts); if (retval && near_miss) *near_miss = 1; // close enough! retval = retval && caster->cast_tick <= tick /* Hasn't cast a spell too recently */ && check->mana <= caster->status.sp && check_prerequisites(caster, check->components); if (retval) { interval_t casttime = check->casttime; if (env->VAR(VAR_MIN_CASTTIME).ty == TYPE::INT) casttime = max(casttime, static_cast<interval_t>(env->VAR(VAR_MIN_CASTTIME).v.v_int)); caster->cast_tick = tick + casttime; /* Make sure not to cast too frequently */ consume_components(caster, check->components); pc_heal(caster, 0, -check->mana); } return retval; }
int skill_power_bl(dumb_ptr<block_list> bl, SkillID skill) { if (bl->bl_type == BL::PC) return skill_power(bl->is_player(), skill); else return 0; }
void magic_free_env(dumb_ptr<env_t> env) { for (int i = 0; i < env->base_env->varv.size(); i++) magic_clear_var(&env->varu[i]); // handled by std::unique_ptr now. Was a memory leak before. // delete[] env->vars; env.delete_(); }
static int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); int invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION ? env->VAR(VAR_INVOCATION).v.v_int : 0; dumb_ptr<invocation> invocation_ = map_id_as_spell(invocation_id); assert (!ARGINT(3)); assert (!ARGINT(4)); assert (!ARGINT(5)); skill_status_effect(subject, static_cast<StatusChange>(ARGINT(1)), ARGINT(2), static_cast<interval_t>(ARGINT(6)), invocation_id); if (invocation_ && subject->bl_type == BL::PC) record_status_change(invocation_, subject->bl_id, StatusChange(ARGINT(1))); return 0; }
static int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY) ? map_id2bl(env->VAR(VAR_CASTER).v.v_int) : NULL; dumb_ptr<block_list> subject = ARGENTITY(0); if (!caster) caster = subject; if (caster->bl_type == BL::PC && subject->bl_type == BL::PC) { dumb_ptr<map_session_data> caster_pc = caster->as_player(); dumb_ptr<map_session_data> subject_pc = subject->as_player(); MAP_LOG_PC(caster_pc, "SPELLHEAL-INSTA PC%d FOR %d", subject_pc->status.char_id, ARGINT(1)); } battle_heal(caster, subject, ARGINT(1), ARGINT(2), 0); return 0; }
// HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる) void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag) { dumb_ptr<map_session_data> sd; nullpo_retv(bl); sd = bl->is_player(); if (sd->status.party_id == party_id) { *flag = 1; sd->party_hp = -1; } }
static void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int desty) { if (target->bl_type == BL::PC || target->bl_type == BL::MOB) { switch (target->bl_type) { case BL::PC: { dumb_ptr<map_session_data> character = target->as_player(); clif_clearchar(character, BeingRemoveWhy::WARPED); map_delblock(character); character->bl_x = destx; character->bl_y = desty; character->bl_m = destm; pc_touch_all_relevant_npcs(character); // Note that touching NPCs may have triggered warping and thereby updated x and y: MapName map_name = character->bl_m->name_; // Warp part #1: update relevant data, interrupt trading etc.: pc_setpos(character, map_name, character->bl_x, character->bl_y, BeingRemoveWhy::GONE); // Warp part #2: now notify the client clif_changemap(character, map_name, character->bl_x, character->bl_y); break; } case BL::MOB: target->bl_x = destx; target->bl_y = desty; target->bl_m = destm; clif_fixmobpos(target->as_mob()); break; } } }
static FString show_entity(dumb_ptr<block_list> entity) { switch (entity->bl_type) { case BL::PC: return entity->as_player()->status.name.to__actual(); case BL::NPC: return entity->as_npc()->name; case BL::MOB: return entity->as_mob()->name; case BL::ITEM: assert (0 && "There is no way this code did what it was supposed to do!"); /* Sorry about this one... */ // WTF? item_data is a struct item, not a struct item_data // return ((struct item_data *) (&entity->as_item()->item_data))->name; abort(); case BL::SPELL: return {"%invocation(ERROR:this-should-not-be-an-entity)"}; default: return {"%unknown-entity"}; } }
static void free_area(dumb_ptr<area_t> area) { if (!area) return; switch (area->ty) { case AREA::UNION: free_area(area->a.a_union[0]); free_area(area->a.a_union[1]); break; default: break; } area.delete_(); }
static int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> psubject = ARGENTITY(0); int charges = ARGINT(1); interval_t attack_delay = static_cast<interval_t>(ARGINT(2)); int attack_range = ARGINT(3); StatusChange icon = StatusChange(ARGINT(4)); int look = ARGINT(5); int stopattack = ARGINT(6); dumb_ptr<map_session_data> subject; if (psubject->bl_type != BL::PC) return 0; subject = psubject->as_player(); if (subject->attack_spell_override) { dumb_ptr<invocation> old_invocation = map_id_as_spell(subject->attack_spell_override); if (old_invocation) spell_free_invocation(old_invocation); } subject->attack_spell_override = trigger_spell(subject->bl_id, env->VAR(VAR_INVOCATION).v.v_int); subject->attack_spell_charges = charges; if (subject->attack_spell_override) { dumb_ptr<invocation> attack_spell = map_id_as_spell(subject->attack_spell_override); if (attack_spell && stopattack) attack_spell->flags |= INVOCATION_FLAG::STOPATTACK; char_set_weapon_icon(subject, charges, icon, look); char_set_attack_info(subject, attack_delay, attack_range); } return 0; }
static void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId dest_id) { #define IFIX(v) if (v == source_id) {v = dest_id; } #define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item) if (!bl) return; switch (bl->bl_type) { case BL::PC: { dumb_ptr<map_session_data> pc = bl->is_player(); for (IOff0 j : IOff0::iter()) IFIX(pc->status.inventory[j].nameid); // cart is no longer supported // IFIX(pc->status.weapon); IFIX(pc->status.shield); IFIX(pc->status.head_top); IFIX(pc->status.head_mid); IFIX(pc->status.head_bottom); Option<P<Storage>> stor_ = account2storage2(pc->status_key.account_id); if OPTION_IS_SOME(stor, stor_) { for (SOff0 j : SOff0::iter()) FIX(stor->storage_[j]); } for (IOff0 j : IOff0::iter()) { P<struct item_data> item = TRY_UNWRAP(pc->inventory_data[j], continue); if (item->nameid == source_id) { item->nameid = dest_id; if (bool(item->equip)) pc_unequipitem(pc, j, CalcStatus::NOW); item->nameid = dest_id; } } break; } case BL::MOB: { dumb_ptr<mob_data> mob = bl->is_mob(); for (Item& itm : mob->lootitemv) FIX(itm); break; } case BL::ITEM: { dumb_ptr<flooritem_data> item = bl->is_item(); FIX(item->item_data); break; } } #undef FIX #undef IFIX }
static void find_entities_in_area_c(dumb_ptr<block_list> target, std::vector<int> *entities_vp, FOREACH_FILTER filter) { switch (target->bl_type) { case BL::PC: if (filter == FOREACH_FILTER::PC || filter == FOREACH_FILTER::ENTITY || (filter == FOREACH_FILTER::TARGET && target->bl_m->flag.pvp)) break; else if (filter == FOREACH_FILTER::SPELL) { /* Check all spells bound to the caster */ dumb_ptr<invocation> invoc = target->as_player()->active_spells; /* Add all spells locked onto thie PC */ while (invoc) { entities_vp->push_back(invoc->bl_id); invoc = invoc->next_invocation; } } return; case BL::MOB: if (filter == FOREACH_FILTER::MOB || filter == FOREACH_FILTER::ENTITY || filter == FOREACH_FILTER::TARGET) break; else return; case BL::SPELL: if (filter == FOREACH_FILTER::SPELL) { dumb_ptr<invocation> invocation = target->as_spell(); /* Check whether the spell is `bound'-- if so, we'll consider it iff we see the caster(case BL::PC). */ if (bool(invocation->flags & INVOCATION_FLAG::BOUND)) return; else break; /* Add the spell */ } else return; case BL::NPC: if (filter == FOREACH_FILTER::NPC) break; else return; default: return; } entities_vp->push_back(target->bl_id); }