summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/spell-language10
-rw-r--r--src/map/magic-expr.c10
-rw-r--r--src/map/magic-interpreter.h1
-rw-r--r--src/map/magic-stmt.c22
-rw-r--r--src/map/pc.c5
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
@@ -733,6 +733,13 @@ fun_is_dead(env_t *env, int args_nr, val_t *result, val_t *args)
}
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)
{
if (ETY(0) == BL_PC
@@ -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);