From 65e4adfc4f90aa087b7cde089029636257761a36 Mon Sep 17 00:00:00 2001
From: Fate <fate-tmw@googlemail.com>
Date: Wed, 17 Jun 2009 19:37:01 +0000
Subject: Added extra checks to ensure spell invocations aren't incorrectly
 deleted

---
 src/map/chat.c       |  4 ++--
 src/map/magic-stmt.c | 18 +++++++++---------
 src/map/magic.h      |  4 ++++
 src/map/map.c        | 16 ++++++++++++----
 src/map/map.h        |  4 ++--
 src/map/skill.c      |  2 +-
 6 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/src/map/chat.c b/src/map/chat.c
index ade4dcb..8af50da 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -137,7 +137,7 @@ int chat_leavechat(struct map_session_data *sd)
 	if(cd->users == 0 && (*cd->owner)->type==BL_PC){
 			// �S�����Ȃ��Ȃ���&PC�̃`���b�g�Ȃ̂ŏ���
 		clif_clearchat(cd,0);
-		map_delobject(cd->bl.id);	// free�܂ł��Ă����
+		map_delobject(cd->bl.id, BL_CHAT);	// free�܂ł��Ă����
 	} else {
 		for(i=leavechar;i < cd->users;i++)
 			cd->usersd[i] = cd->usersd[i+1];
@@ -307,7 +307,7 @@ int chat_deletenpcchat(struct npc_data *nd)
 	
 	chat_npckickall(cd);
 	clif_clearchat(cd,0);
-	map_delobject(cd->bl.id);	// free�܂ł��Ă����
+	map_delobject(cd->bl.id, BL_CHAT);	// free�܂ł��Ă����
 	nd->chat_id=0;
 	
 	return 0;
diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c
index a8d42f1..e488c2b 100644
--- a/src/map/magic-stmt.c
+++ b/src/map/magic-stmt.c
@@ -76,8 +76,8 @@ clear_stack(invocation_t *invocation)
         invocation->stack_size = 0;
 }
 
-static void
-free_invocation(invocation_t *invocation)
+void
+spell_free_invocation(invocation_t *invocation)
 {
         if (invocation->status_change_refs) {
                 free(invocation->status_change_refs);
@@ -100,7 +100,7 @@ free_invocation(invocation_t *invocation)
         magic_free_env(invocation->env);
 
 	map_delblock(&invocation->bl);
-        map_delobject(invocation->bl.id); // also frees the object
+        map_delobject(invocation->bl.id, BL_SPELL); // also frees the object
 //        free(invocation);
 }
 
@@ -152,12 +152,12 @@ magic_stop_completely(character_t *c)
                 c->sc_data[i].spell_invocation = 0;
 
         while (c->active_spells)
-                free_invocation(c->active_spells);
+                spell_free_invocation(c->active_spells);
 
         if (c->attack_spell_override) {
                 invocation_t *attack_spell = (invocation_t *)map_id2bl(c->attack_spell_override);
                 if (attack_spell)
-                        free_invocation(attack_spell);
+                        spell_free_invocation(attack_spell);
                 c->attack_spell_override = 0;
                 char_set_weapon_icon(c, 0, 0, 0);
                 char_set_attack_info(c, 0, 0);
@@ -175,7 +175,7 @@ try_to_finish_invocation(invocation_t *invocation)
                         invocation->end_effect = NULL;
                         spell_execute(invocation);
                 } else
-                        free_invocation(invocation);
+                        spell_free_invocation(invocation);
         }
 }
 
@@ -517,7 +517,7 @@ op_override_attack(env_t *env, int args_nr, val_t *args)
         if (subject->attack_spell_override) {
                 invocation_t *old_invocation = (invocation_t *)map_id2bl(subject->attack_spell_override);
                 if (old_invocation)
-                        free_invocation(old_invocation);
+                        spell_free_invocation(old_invocation);
         }
 
         subject->attack_spell_override = trigger_spell(subject->bl.id, VAR(VAR_INVOCATION).v.v_int);
@@ -1452,7 +1452,7 @@ spell_attack(int caster_id, int target_id)
         if (invocation
             && caster->attack_spell_override != invocation->bl.id) {
                 /* Attack spell changed / was refreshed */
-                // free_invocation(invocation); // [Fate] This would be a double free.
+                // spell_free_invocation(invocation); // [Fate] This would be a double free.
         } else if (!invocation
                    || caster->attack_spell_charges <= 0) {
                 caster->attack_spell_override = 0;
@@ -1463,7 +1463,7 @@ spell_attack(int caster_id, int target_id)
                         pc_stopattack(caster);
 
                 if (invocation)
-                        free_invocation(invocation);
+                        spell_free_invocation(invocation);
         }
 
         return 1;
diff --git a/src/map/magic.h b/src/map/magic.h
index 9ca47bb..49f2883 100644
--- a/src/map/magic.h
+++ b/src/map/magic.h
@@ -92,4 +92,8 @@ magic_stop_completely(character_t *c);
 int
 spell_attack(int caster, int target);
 
+
+void
+spell_free_invocation(struct invocation *invocation);
+
 #endif /* !defined(MAGIC_H_) */
diff --git a/src/map/map.c b/src/map/map.c
index 128d50b..1acae20 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -575,10 +575,15 @@ int map_addobject(struct block_list *bl) {
  *	map_delobject��free���Ȃ��o�[�W����
  *------------------------------------------
  */
-int map_delobjectnofree(int id) {
+int map_delobjectnofree(int id, int type) {
 	if(object[id]==NULL)
 		return 0;
 
+        if (object[id]->type != type) {
+                fprintf(stderr, "Incorrect type: expected %d, got %d\n", type, object[id]->type);
+                *((char *) 0) = 0; // break for backtrace
+        }
+
 	map_delblock(object[id]);
 	numdb_erase(id_db,id);
 //	map_freeblock(object[id]);
@@ -601,13 +606,13 @@ int map_delobjectnofree(int id) {
  * add�Ƃ̑Ώ̐��������̂��C�ɂȂ�
  *------------------------------------------
  */
-int map_delobject(int id) {
+int map_delobject(int id, int type) {
 	struct block_list *obj = object[id];
 
 	if(obj==NULL)
 		return 0;
 
-	map_delobjectnofree(id);
+	map_delobjectnofree(id, type);
         if (obj->type == BL_PC) // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from
                 pc_cleanup((struct map_session_data *)obj);
 
@@ -675,7 +680,7 @@ int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
 	if(data)
 		delete_timer(fitem->cleartimer,map_clearflooritem_timer);
 	clif_clearflooritem(fitem,0);
-	map_delobject(fitem->bl.id);
+	map_delobject(fitem->bl.id, BL_ITEM);
 
 	return 0;
 }
@@ -1752,6 +1757,9 @@ static int cleanup_sub(struct block_list *bl, va_list ap) {
         case BL_SKILL:
             skill_delunit((struct skill_unit *) bl);
             break;
+        case BL_SPELL:
+            spell_free_invocation((struct invocation *) bl);
+            break;
         }
 
 	return 0;
diff --git a/src/map/map.h b/src/map/map.h
index c678501..ceb3bbf 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -667,8 +667,8 @@ int map_countnearpc(int,int,int);
 int map_count_oncell(int m,int x,int y);
 // �ꎞ�Iobject�֘A
 int map_addobject(struct block_list *);
-int map_delobject(int);
-int map_delobjectnofree(int id);
+int map_delobject(int, int type);
+int map_delobjectnofree(int id, int type);
 void map_foreachobject(int (*)(struct block_list*,va_list),int,...);
 //
 int map_quit(struct map_session_data *);
diff --git a/src/map/skill.c b/src/map/skill.c
index af56cab..3a777ac 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -9225,7 +9225,7 @@ int skill_delunit(struct skill_unit *unit)
 
 	unit->group=NULL;
 	unit->alive=0;
-	map_delobjectnofree(unit->bl.id);
+	map_delobjectnofree(unit->bl.id, BL_SKILL);
 	if(group->alive_count>0 && (--group->alive_count)<=0)
 		skill_delunitgroup(group);
 
-- 
cgit v1.2.3-70-g09d2