From d2bc97170e91765de7ab67b017085370a26e3f93 Mon Sep 17 00:00:00 2001 From: Fate Date: Sat, 31 Jan 2009 12:57:07 -0700 Subject: When running out of spell charges, make sure to use spell attack delay for last attack, too --- doc/spell-language | 10 ++++++++-- src/map/magic-expr.c | 10 +++++++++- src/map/magic-interpreter.h | 1 + src/map/magic-stmt.c | 22 ++++++++++++++++++---- src/map/pc.c | 5 +++-- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/doc/spell-language b/doc/spell-language index b4ef833..68c15c8 100644 --- a/doc/spell-language +++ b/doc/spell-language @@ -561,6 +561,9 @@ The following functions are available: PCs gain such experience points by killing/completing quests, though this `healer experience point pool' slowly drains itself. + + is_pc : entity -> bool + Determines whether the target is a player character + Operations: ----------- This section documents the operations API. @@ -629,8 +632,8 @@ This section documents the operations API. change has finished. + override_attack : entity * int * int - * int * int *int -> () - override_attack(entity, charges, delay, range, icon, animation) + * int * int *int * int -> () + override_attack(entity, charges, delay, range, icon, animation, stop) overrides the entity's current attack (only for PCs). The entity will have `charges' attacks that instead result in calling the ATTRIGGER effect for this spell. When this operation is called, @@ -643,6 +646,9 @@ This section documents the operations API. `icon' is the ID of a status-effect ID that will be displayed while the spell is in effect. `animation' is the attack animation ID that should be used. + `stop' decides whether attacking should stop once the spell is out + of charges (1) or continue (0). (Note: this doesn't properly work, + possibly due to client issues. Always use 0.) Note that if the ATTRIGGER effect ABORTs, no charge will be consumed. diff --git a/src/map/magic-expr.c b/src/map/magic-expr.c index cb3c0ae..31abe13 100644 --- a/src/map/magic-expr.c +++ b/src/map/magic-expr.c @@ -732,6 +732,13 @@ fun_is_dead(env_t *env, int args_nr, val_t *result, val_t *args) return 0; } +static int +fun_is_pc(env_t *env, int args_nr, val_t *result, val_t *args) +{ + RESULTINT = (ETY(0) == BL_PC); + return 0; +} + static int fun_partner(env_t *env, int args_nr, val_t *result, val_t *args) { @@ -941,7 +948,7 @@ fun_rbox(env_t *env, int args_nr, val_t *result, val_t *args) static int fun_running_status_update(env_t *env, int args_nr, val_t *result, val_t *args) { - if (ETY(0) != BL_PC) + if (ETY(0) != BL_PC && ETY(0) != BL_MOB) return 1; RESULTINT = battle_get_sc_data(ARGENTITY(0))[ARGINT(1)].timer != -1; @@ -1189,6 +1196,7 @@ static fun_t functions[] = { { "map_nr", "l", 'i', fun_map_nr }, { "dir_towards", "lli", 'd', fun_dir_towards }, { "is_dead", "e", 'i', fun_is_dead }, + { "is_pc", "e", 'i', fun_is_pc }, { "extract_healer_experience", "ei", 'i', fun_extract_healer_xp }, { NULL, NULL, '.', NULL } }; diff --git a/src/map/magic-interpreter.h b/src/map/magic-interpreter.h index ebc49ee..bef759a 100644 --- a/src/map/magic-interpreter.h +++ b/src/map/magic-interpreter.h @@ -330,6 +330,7 @@ typedef struct status_change_ref { #define INVOCATION_FLAG_BOUND (1 << 0) /* Bound directly to the caster (i.e., ignore its location) */ #define INVOCATION_FLAG_ABORTED (1 << 1) /* Used `abort' to terminate */ +#define INVOCATION_FLAG_STOPATTACK (1 << 2) /* On magical attacks: if we run out of steam, stop attacking altogether */ typedef struct invocation { struct block_list bl; diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c index b5128e3..f8606b8 100644 --- a/src/map/magic-stmt.c +++ b/src/map/magic-stmt.c @@ -472,7 +472,7 @@ op_status_change(env_t *env, int args_nr, val_t *args) skill_status_effect(subject, ARGINT(1), ARGINT(2), ARGINT(3), ARGINT(4), ARGINT(5), ARGINT(6), 0, invocation_id); - if (invocation) + if (invocation && subject->type == BL_PC) record_status_change(invocation, subject->id, ARGINT(1)); return 0; @@ -487,6 +487,7 @@ op_override_attack(env_t *env, int args_nr, val_t *args) int attack_range = ARGINT(3); int icon = ARGINT(4); int look = ARGINT(5); + int stopattack = ARGINT(6); character_t *subject; if (psubject->type != BL_PC) @@ -504,6 +505,10 @@ op_override_attack(env_t *env, int args_nr, val_t *args) subject->attack_spell_charges = charges; if (subject->attack_spell_override) { + invocation_t *attack_spell = (invocation_t *)map_id2bl(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); } @@ -780,7 +785,7 @@ static op_t operations[] = { "warp", "el", op_warp }, { "banish", "e", op_banish }, { "status_change", "eiiiiii", op_status_change }, - { "override_attack", "eiiiii", op_override_attack }, + { "override_attack", "eiiiiii", op_override_attack }, { "create_item", "e.i", op_create_item }, { "aggravate", "eie", op_aggravate }, { "spawn", "aeiiii", op_spawn }, @@ -852,7 +857,9 @@ spell_effect_report_termination(int invocation_id, int bl_id, int sc_id, int sup } if (index == -1) { - fprintf(stderr, "[magic] INTERNAL ERROR: spell-effect-report-termination: tried to terminate on unexpected bl %d, sc %d\n", bl_id, sc_id); + entity_t *entity = map_id2bl(bl_id); + if (entity->type == BL_PC) + fprintf(stderr, "[magic] INTERNAL ERROR: spell-effect-report-termination: tried to terminate on unexpected bl %d, sc %d\n", bl_id, sc_id); return; } @@ -1394,12 +1401,16 @@ spell_attack(int caster_id, int target_id) { character_t *caster = (character_t *)map_id2bl(caster_id); invocation_t *invocation; + int stop_attack = 0; if (!caster) - return 1; + return 0; invocation = (invocation_t *)map_id2bl(caster->attack_spell_override); + if (invocation && invocation->flags & INVOCATION_FLAG_STOPATTACK) + stop_attack = 1; + if (invocation && caster->attack_spell_charges > 0) { magic_clear_var(&invocation->env->vars[VAR_TARGET]); @@ -1428,6 +1439,9 @@ spell_attack(int caster_id, int target_id) char_set_weapon_icon(caster, 0, 0, 0); char_set_attack_info(caster, 0, 0); + if (stop_attack) + pc_stopattack(caster); + if (invocation) free_invocation(invocation); } diff --git a/src/map/pc.c b/src/map/pc.c index 0eac9eb..e6efe45 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4149,7 +4149,7 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) struct status_change *sc_data; short *opt; int dist,skill,range; - + int attack_spell_delay; sd=map_id2sd(id); if(sd == NULL) @@ -4203,10 +4203,11 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data) if (sd->attackabletime > tick) return 0; // cannot attack yet + attack_spell_delay = sd->attack_spell_delay; if (sd->attack_spell_override // [Fate] If we have an active attack spell, use that && spell_attack(id, sd->attacktarget)) { // Return if the spell succeeded. If the spell had disspiated, spell_attack() may fail. - sd->attackabletime = tick + sd->attack_spell_delay; + sd->attackabletime = tick + attack_spell_delay; } else { dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y); -- cgit v1.2.3-60-g2f50