From 90735f447e12393f3d89b8c053bd4d8c8a707fa2 Mon Sep 17 00:00:00 2001
From: Jared Adams <jaxad0127@gmail.com>
Date: Sun, 26 Oct 2008 20:40:30 +0000
Subject: Commit Mantis 509

---
 src/map/magic-interpreter-base.c |  36 ++++++-----
 src/map/magic-interpreter.h      |   5 +-
 src/map/magic-stmt.c             | 115 +++++++++++++++++++++++++++-------
 src/map/magic.c                  |   8 ++-
 src/map/map.c                    | 131 +++++++++++++++++++++++++++++++--------
 src/map/map.h                    |   4 ++
 src/map/pc.c                     |   7 ++-
 7 files changed, 243 insertions(+), 63 deletions(-)

(limited to 'src')

diff --git a/src/map/magic-interpreter-base.c b/src/map/magic-interpreter-base.c
index 9be6f81..9338c78 100644
--- a/src/map/magic-interpreter-base.c
+++ b/src/map/magic-interpreter-base.c
@@ -288,14 +288,19 @@ consume_components(character_t *caster, component_t *component)
 
 
 static int
-spellguard_can_satisfy(spellguard_check_t *check, character_t *caster, env_t *env)
+spellguard_can_satisfy(spellguard_check_t *check, character_t *caster, env_t *env, int *near_miss)
 {
         int tick = gettick();
 
-        int retval = (caster->cast_tick <= tick /* Hasn't cast a spell too recently */
-                      && check->mana <= caster->status.sp
-                      && check_prerequisites(caster, check->catalysts)
-                      && check_prerequisites(caster, check->components));
+        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) {
                 int casttime = check->casttime;
@@ -313,7 +318,7 @@ spellguard_can_satisfy(spellguard_check_t *check, character_t *caster, env_t *en
 }
 
 static effect_set_t *
-spellguard_check_sub(spellguard_check_t *check, spellguard_t *guard, character_t *caster, env_t *env)
+spellguard_check_sub(spellguard_check_t *check, spellguard_t *guard, character_t *caster, env_t *env, int *near_miss)
 {
         if (guard == NULL)
                 return NULL;
@@ -342,13 +347,13 @@ spellguard_check_sub(spellguard_check_t *check, spellguard_t *guard, character_t
                 copy_components(&altcheck.catalysts, check->catalysts);
                 copy_components(&altcheck.components, check->components);
 
-                retval = spellguard_check_sub(&altcheck, guard->next, caster, env);
+                retval = spellguard_check_sub(&altcheck, guard->next, caster, env, near_miss);
                 free_components(&altcheck.catalysts);
                 free_components(&altcheck.components);
                 if (retval)
                         return retval;
                 else
-                    return spellguard_check_sub(check, guard->s.s_alt, caster, env);
+                    return spellguard_check_sub(check, guard->s.s_alt, caster, env, near_miss);
         }
 
         case SPELLGUARD_MANA:
@@ -360,7 +365,7 @@ spellguard_check_sub(spellguard_check_t *check, spellguard_t *guard, character_t
                 break;
 
         case SPELLGUARD_EFFECT:
-                if (spellguard_can_satisfy(check, caster, env))
+                if (spellguard_can_satisfy(check, caster, env, near_miss))
                         return &guard->s.s_effect;
                 else
                         return NULL;    
@@ -370,11 +375,11 @@ spellguard_check_sub(spellguard_check_t *check, spellguard_t *guard, character_t
                 return NULL;
         }
 
-        return spellguard_check_sub(check, guard->next, caster, env);
+        return spellguard_check_sub(check, guard->next, caster, env, near_miss);
 }
 
 static effect_set_t *
-check_spellguard(spellguard_t *guard, character_t *caster, env_t *env)
+check_spellguard(spellguard_t *guard, character_t *caster, env_t *env, int *near_miss)
 {
         spellguard_check_t check;
         effect_set_t *retval;
@@ -382,7 +387,7 @@ check_spellguard(spellguard_t *guard, character_t *caster, env_t *env)
         check.components = NULL;
         check.mana = check.casttime = 0;
 
-        retval = spellguard_check_sub(&check, guard, caster, env);
+        retval = spellguard_check_sub(&check, guard, caster, env, near_miss);
 
         free_components(&check.catalysts);
         free_components(&check.components);
@@ -396,17 +401,20 @@ check_spellguard(spellguard_t *guard, character_t *caster, env_t *env)
 
 
 effect_set_t *
-spell_trigger(spell_t *spell, character_t *caster, env_t *env)
+spell_trigger(spell_t *spell, character_t *caster, env_t *env, int *near_miss)
 {
         int i;
         spellguard_t *guard = spell->spellguard;
 
+        if (near_miss)
+            *near_miss = 0;
+
         for (i = 0; i < spell->letdefs_nr; i++)
                 magic_eval(env,
                            &env->vars[spell->letdefs[i].id],
                            spell->letdefs[i].expr);
 
-        return check_spellguard(guard, caster, env);
+        return check_spellguard(guard, caster, env, near_miss);
 }
 
 static void
diff --git a/src/map/magic-interpreter.h b/src/map/magic-interpreter.h
index 94c32bc..9fc6308 100644
--- a/src/map/magic-interpreter.h
+++ b/src/map/magic-interpreter.h
@@ -377,8 +377,11 @@ spell_create_env(magic_conf_t *conf, spell_t *spell, character_t *caster, int sp
 void
 magic_free_env(env_t *env);
 
+/**
+ * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components)
+ */
 effect_set_t *
-spell_trigger(spell_t *spell, character_t *caster, env_t *env);
+spell_trigger(spell_t *spell, character_t *caster, env_t *env, int *near_miss);
 
 invocation_t *
 spell_instantiate(effect_set_t *effect, env_t *env);
diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c
index 49c75b1..30b79d1 100644
--- a/src/map/magic-stmt.c
+++ b/src/map/magic-stmt.c
@@ -504,15 +504,47 @@ op_override_attack(env_t *env, int args_nr, val_t *args)
         return 0;
 }
 
+static int // ret -1: not a string, ret 1: no such item, ret 0: OK
+find_item(val_t *args, int index, struct item *item, int *stackable)
+{
+        struct item_data *item_data;
+        int must_add_sequentially;
+
+        if (TY(index) == TY_INT)
+                item_data = itemdb_exists(ARGINT(index));
+        else if (TY(index) == TY_STRING)
+                item_data = itemdb_searchname(ARGSTR(index));
+        else
+                return -1;
+
+        if (!item_data)
+                return 1;
+
+        must_add_sequentially = (item_data->type == 4
+                                 || item_data->type == 5
+                                 || item_data->type == 7
+                                 || item_data->type == 8); /* Very elegant. */
+
+
+        if (stackable)
+            *stackable = !must_add_sequentially;
+
+        memset(item, 0, sizeof(struct item));
+        item->nameid = item_data->nameid;
+        item->identify = 1;
+
+        return 0;
+}
+
+#define GET_ARG_ITEM(index, dest, stackable) switch(find_item(args, index, &dest, &stackable)) { case -1 : return 1; case 1 : return 0; }
 
 static int
 op_create_item(env_t *env, int args_nr, val_t *args)
 {
-        struct item_data *item_data;
         struct item item;
         entity_t *entity = ARGENTITY(0);
         character_t *subject;
-        int must_add_sequentially;
+        int stackable;
         int count = ARGINT(2);
         if (count <= 0)
                 return 0;
@@ -522,26 +554,9 @@ op_create_item(env_t *env, int args_nr, val_t *args)
         else
                 return 0;
 
-        if (TY(1) == TY_INT)
-                item_data = itemdb_exists(ARGINT(1));
-        else if (TY(1) == TY_STRING)
-                item_data = itemdb_searchname(ARGSTR(1));
-        else
-                return 1;
-
-        if (!item_data)
-                return 0;
-
-        must_add_sequentially = (item_data->type == 4
-                                 || item_data->type == 5
-                                 || item_data->type == 7
-                                 || item_data->type == 8); /* Very elegant. */
-
-        memset(&item, 0, sizeof(struct item));
-        item.nameid = item_data->nameid;
-        item.identify = 1;
+        GET_ARG_ITEM(1, item, stackable);
 
-        if (must_add_sequentially)
+        if (!stackable)
                 while (count--)
                         pc_additem(subject, &item, 1);
         else
@@ -709,6 +724,60 @@ op_set_script_variable(env_t *env, int args_nr, val_t *args)
 }
 
 
+static int
+op_set_hair_colour(env_t *env, int args_nr, val_t *args)
+{
+        character_t *c = (ETY(0) == BL_PC)? ARGPC(0) : NULL;
+
+        if (!c)
+                return 1;
+
+        pc_changelook(c, LOOK_HAIR_COLOR, ARGINT(1));
+
+        return 0;
+}
+
+
+static int
+op_set_hair_style(env_t *env, int args_nr, val_t *args)
+{
+        character_t *c = (ETY(0) == BL_PC)? ARGPC(0) : NULL;
+
+        if (!c)
+                return 1;
+
+        pc_changelook(c, LOOK_HAIR, ARGINT(1));
+
+        return 0;
+}
+
+static int
+op_drop_item_for(env_t *env, int args_nr, val_t *args)
+{
+        struct item item;
+        int stackable;
+        location_t *loc = &ARGLOCATION(0);
+        int count = ARGINT(2);
+        int time = ARGINT(3);
+        character_t *c = ((args_nr > 4) && (ETY(4) == BL_PC))? ARGPC(4) : NULL;
+        int delay = (args_nr > 5)? ARGINT(5) : 0;
+        int delaytime[3] = { delay, delay, delay };
+        character_t *owners[3] = { c, NULL, NULL };
+
+        GET_ARG_ITEM(1, item, stackable);
+
+        if (stackable)
+                map_addflooritem_any(&item, count, loc->m, loc->x, loc->y,
+                                     owners, delaytime,
+                                     time, 0);
+        else while (count-- > 0)
+                map_addflooritem_any(&item, 1, loc->m, loc->x, loc->y,
+                                     owners, delaytime,
+                                     time, 0);
+
+        return 0;
+}
+
 static op_t operations[] =
 {
         { "sfx", ".ii", op_sfx },
@@ -729,6 +798,10 @@ static op_t operations[] =
         { "injure", "eeii", op_injure },
         { "emote", "ei", op_emote },
         { "set_script_variable", "esi", op_set_script_variable },
+        { "set_hair_colour", "ei", op_set_hair_colour },
+        { "set_hair_style", "ei", op_set_hair_style },
+        { "drop_item", "l.ii", op_drop_item_for },
+        { "drop_item_for", "l.iiei", op_drop_item_for },
         { NULL, NULL, NULL }
 };
 
diff --git a/src/map/magic.c b/src/map/magic.c
index 114f74d..7309281 100644
--- a/src/map/magic.c
+++ b/src/map/magic.c
@@ -76,8 +76,9 @@ magic_message(character_t *caster,
         free(spell_invocation);
 
         if (spell) {
+                int near_miss;
                 env_t *env = spell_create_env(&magic_conf, spell, caster, power, parameter);
-                effect_set_t *effects = spell_trigger(spell, caster, env);
+                effect_set_t *effects = spell_trigger(spell, caster, env, &near_miss);
 
 #ifdef DEBUG
                 fprintf(stderr, "Found spell `%s', triggered = %d\n", spell_, effects != NULL);
@@ -99,6 +100,11 @@ magic_message(character_t *caster,
                         return (spell->flags & SPELL_FLAG_SILENT)? -1 : 1;
                 } else {
                         magic_free_env(env);
+
+                        /* Obscure proper almost-triggered spell */
+                        if (near_miss)
+                                while (*source_invocation)
+                                        *source_invocation++ = '.';
                 }
                 return 0;
         }
diff --git a/src/map/map.c b/src/map/map.c
index 079da90..30b9d78 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -783,15 +783,18 @@ int map_searchrandfreecell(int m,int x,int y,int range) {
  * item_data��amount�ȊO��copy����
  *------------------------------------------
  */
-int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct map_session_data *first_sd,
-    struct map_session_data *second_sd,struct map_session_data *third_sd,int type) {
+int map_addflooritem_any(struct item *item_data, int amount, int m, int x, int y,
+                         struct map_session_data **owners,
+                         int *owner_protection,
+                         int lifetime, int dispersal)
+{
 	int xy,r;
 	unsigned int tick;
 	struct flooritem_data *fitem=NULL;
 
 	nullpo_retr(0, item_data);
 
-	if((xy=map_searchrandfreecell(m,x,y,1))<0)
+	if((xy=map_searchrandfreecell(m,x,y, dispersal))<0)
 		return 0;
 	r=rand();
 
@@ -815,33 +818,24 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct
 	}
 
 	tick = gettick();
-	if(first_sd) {
-		fitem->first_get_id = first_sd->bl.id;
-		if(type)
-			fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time;
-		else
-			fitem->first_get_tick = tick + battle_config.item_first_get_time;
-	}
-	if(second_sd) {
-		fitem->second_get_id = second_sd->bl.id;
-		if(type)
-			fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time;
-		else
-			fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time;
-	}
-	if(third_sd) {
-		fitem->third_get_id = third_sd->bl.id;
-		if(type)
-			fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time;
-		else
-			fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time;
-	}
+
+	if (owners[0])
+                fitem->first_get_id = owners[0]->bl.id;
+        fitem->first_get_tick = tick + owner_protection[0];
+
+	if (owners[1])
+                fitem->second_get_id = owners[1]->bl.id;
+        fitem->second_get_tick = tick + owner_protection[1];
+
+	if (owners[2])
+                fitem->third_get_id = owners[2]->bl.id;
+        fitem->third_get_tick = tick + owner_protection[2];
 
 	memcpy(&fitem->item_data,item_data,sizeof(*item_data));
 	fitem->item_data.amount=amount;
 	fitem->subx=(r&3)*3+3;
 	fitem->suby=((r>>2)&3)*3+3;
-	fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
+	fitem->cleartimer=add_timer(gettick() + lifetime, map_clearflooritem_timer, fitem->bl.id, 0);
 
 	map_addblock(&fitem->bl);
 	clif_dropflooritem(fitem);
@@ -849,6 +843,93 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct
 	return fitem->bl.id;
 }
 
+
+int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct map_session_data *first_sd,
+    struct map_session_data *second_sd,struct map_session_data *third_sd,int type)
+{
+        struct map_session_data *owners[3] = { first_sd, second_sd, third_sd };
+        int owner_protection[3];
+
+        if (type) {
+                owner_protection[0] = battle_config.mvp_item_first_get_time;
+                owner_protection[1] = owner_protection[0] + battle_config.mvp_item_second_get_time;
+                owner_protection[2] = owner_protection[1] + battle_config.mvp_item_third_get_time;
+        } else {
+                owner_protection[0] = battle_config.item_first_get_time;
+                owner_protection[1] = owner_protection[0] + battle_config.item_second_get_time;
+                owner_protection[2] = owner_protection[1] + battle_config.item_third_get_time;
+        }
+
+        return map_addflooritem_any(item_data, amount, m, x, y,
+                                    owners, owner_protection,
+                                    battle_config.flooritem_lifetime,
+                                    1);
+}
+
+/* 	int xy,r; */
+/* 	unsigned int tick; */
+/* 	struct flooritem_data *fitem=NULL; */
+
+/* 	nullpo_retr(0, item_data); */
+
+/* 	if((xy=map_searchrandfreecell(m,x,y,1))<0) */
+/* 		return 0; */
+/* 	r=rand(); */
+
+/* 	fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem)); */
+/* 	fitem->bl.type=BL_ITEM; */
+/* 	fitem->bl.prev = fitem->bl.next = NULL; */
+/* 	fitem->bl.m=m; */
+/* 	fitem->bl.x=xy&0xffff; */
+/* 	fitem->bl.y=(xy>>16)&0xffff; */
+/* 	fitem->first_get_id = 0; */
+/* 	fitem->first_get_tick = 0; */
+/* 	fitem->second_get_id = 0; */
+/* 	fitem->second_get_tick = 0; */
+/* 	fitem->third_get_id = 0; */
+/* 	fitem->third_get_tick = 0; */
+
+/* 	fitem->bl.id = map_addobject(&fitem->bl); */
+/* 	if(fitem->bl.id==0){ */
+/* 		free(fitem); */
+/* 		return 0; */
+/* 	} */
+
+/* 	tick = gettick(); */
+/* 	if(first_sd) { */
+/* 		fitem->first_get_id = first_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time; */
+/* 		else */
+/* 			fitem->first_get_tick = tick + battle_config.item_first_get_time; */
+/* 	} */
+/* 	if(second_sd) { */
+/* 		fitem->second_get_id = second_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time; */
+/* 		else */
+/* 			fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time; */
+/* 	} */
+/* 	if(third_sd) { */
+/* 		fitem->third_get_id = third_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time; */
+/* 		else */
+/* 			fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time; */
+/* 	} */
+
+/* 	memcpy(&fitem->item_data,item_data,sizeof(*item_data)); */
+/* 	fitem->item_data.amount=amount; */
+/* 	fitem->subx=(r&3)*3+3; */
+/* 	fitem->suby=((r>>2)&3)*3+3; */
+/* 	fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); */
+
+/* 	map_addblock(&fitem->bl); */
+/* 	clif_dropflooritem(fitem); */
+
+/* 	return fitem->bl.id; */
+/* } */
+
 /*==========================================
  * charid_db�֒lj�(�ԐM�҂�������ΕԐM)
  *------------------------------------------
diff --git a/src/map/map.h b/src/map/map.h
index ea240f2..dfed77f 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -686,6 +686,10 @@ int map_addnpc(int,struct npc_data *);
 // ���A�C�e���֘A
 int map_clearflooritem_timer(int,unsigned int,int,int);
 #define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1)
+int map_addflooritem_any(struct item *,int amount,int m,int x,int y,
+                         struct map_session_data **owners,
+                         int *owner_protection,
+                         int lifetime, int dispersal);
 int map_addflooritem(struct item *,int,int,int,int,struct map_session_data *,struct map_session_data *,struct map_session_data *,int);
 int map_searchrandfreecell(int,int,int,int);
 
diff --git a/src/map/pc.c b/src/map/pc.c
index 64057e7..2d4e48c 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -3058,19 +3058,24 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
                 fitem->third_get_id = 0;
         }
 
+fprintf(stderr, "pickuptime = %d, ticktime = %d\n", fitem->first_get_tick, tick);
+fprintf(stderr, "canpickup-1 = %d\n", can_pick_item_up_from (sd, fitem->second_get_id));
         can_take = can_pick_item_up_from (sd, fitem->first_get_id);
-
+fprintf(stderr, "Can take at L%d? %d\n", __LINE__, can_take);
         if (!can_take)
                 can_take = fitem->first_get_tick <= tick
                         && can_pick_item_up_from (sd, fitem->second_get_id);
+fprintf(stderr, "Can take at L%d? %d\n", __LINE__, can_take);
 
         if (!can_take)
                 can_take = fitem->second_get_tick <= tick
                         && can_pick_item_up_from (sd, fitem->third_get_id);
 
+fprintf(stderr, "Can take at L%d? %d\n", __LINE__, can_take);
         if (!can_take)
                 can_take = fitem->third_get_tick <= tick;
 
+fprintf(stderr, "Can take at L%d? %d\n", __LINE__, can_take);
         if (can_take) {
                 /* Can pick up */
 
-- 
cgit v1.2.3-70-g09d2