From a91ff26a6036ad42b1477e5e27f9eea41223ac25 Mon Sep 17 00:00:00 2001 From: Andrey Voitishin Date: Sun, 1 Feb 2015 22:40:37 -0500 Subject: [PATCH] + actor_before_death script call back (set in bind_stalker). This will allow scripts to process actor condition and prevent actor's death or kill him if desired. IMPORTANT: if you wish to kill actor you need to call db.actor:kill(level:object_by_id(whoID), true) in actor_before_death callback, to ensure all objects are properly destroyed. + set_health_ex script method for game_object. This will directly set entity's health instead of going through health property which operates on delta --- res/gamedata/scripts/bind_stalker.script | 9 +++++++++ src/xrGame/Entity.cpp | 14 ++++++++++++-- src/xrGame/Entity.h | 4 ++-- src/xrGame/game_object_space.h | 10 ++++++---- src/xrGame/script_game_object.h | 5 +++-- src/xrGame/script_game_object4.cpp | 10 ++++++++++ src/xrGame/script_game_object_script.cpp | 10 ++++++---- src/xrGame/script_game_object_script3.cpp | 5 +++-- src/xrGame/script_game_object_use.cpp | 4 ++-- 9 files changed, 53 insertions(+), 18 deletions(-) diff --git a/res/gamedata/scripts/bind_stalker.script b/res/gamedata/scripts/bind_stalker.script index 6b006e7bb4e..b9874f2fc8d 100644 --- a/res/gamedata/scripts/bind_stalker.script +++ b/res/gamedata/scripts/bind_stalker.script @@ -95,6 +95,7 @@ function actor_binder:net_destroy() self.object:set_callback(callback.item_to_belt, nil) self.object:set_callback(callback.item_to_ruck, nil) self.object:set_callback(callback.item_to_slot, nil) + self.object:set_callback(callback.actor_before_death, nil) ----| end:aVo |---------------------------------------------------------------- log("--------->"..tostring(_G.amb_vol)) @@ -141,6 +142,7 @@ function actor_binder:reinit() self.object:set_callback(callback.item_to_ruck, self.item_to_ruck, self) self.object:set_callback(callback.item_to_belt, self.item_to_belt, self) self.object:set_callback(callback.item_to_slot, self.item_to_slot, self) + self.object:set_callback(callback.actor_before_death, self.on_actor_before_death, self) ----| end:aVo |---------------------------------------------------------------- end --------------------------------------------------------------------------------------------------------------------- @@ -197,6 +199,13 @@ end function actor_binder:item_to_slot(obj) log(string.format("item_to_slot [%s]", obj:name())) end +-- actor before death callback +-- IMPORTANT: if you wish to kill actor you need to call db.actor:kill(level:object_by_id(whoID), true) in actor_before_death callback, to ensure all objects are properly destroyed. +function actor_binder:on_actor_before_death(whoID) +-- log("[AVO] on_actor_before_death callback") +-- db.actor:set_health_ex(1) + db.actor:kill(level:object_by_id(whoID), true) +end ----| end:aVo |--------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------- function actor_binder:take_item_from_box(box, item) diff --git a/src/xrGame/Entity.cpp b/src/xrGame/Entity.cpp index 8a311a2ab14..78fbd6b184c 100644 --- a/src/xrGame/Entity.cpp +++ b/src/xrGame/Entity.cpp @@ -252,12 +252,22 @@ void CEntity::net_Destroy() set_ready_to_save(); } -void CEntity::KillEntity(u16 whoID) +void CEntity::KillEntity(u16 whoID, bool bypass_actor_check) { + //AVO: allow scripts to process actor condition and prevent actor's death or kill him if desired. + //IMPORTANT: if you wish to kill actor you need to call db.actor:kill(level:object_by_id(whoID), true) in actor_before_death callback, to ensure all objects are properly destroyed + // this will bypass below if block and go to normal KillEntity routine. + if (IsGameTypeSingle() && this->ID() == Actor()->ID() && bypass_actor_check != true) + { + Actor()->callback(GameObject::eActorBeforeDeath)(whoID); + return; + } + //-AVO + if (this->ID() == Actor()->ID()) { Actor()->detach_Vehicle(); - Actor()->use_MountedWeapon(NULL); + Actor()->use_MountedWeapon(nullptr); } if (whoID != ID()) { diff --git a/src/xrGame/Entity.h b/src/xrGame/Entity.h index 4bafe96c77c..e2dc59a756b 100644 --- a/src/xrGame/Entity.h +++ b/src/xrGame/Entity.h @@ -94,8 +94,8 @@ class CEntity : public CPhysicsShellHolder, public CDamageManager virtual void HitImpulse(float P, Fvector& vWorldDir, Fvector& vLocalDir) = 0; virtual void Die(IGameObject* who); - // void KillEntity (IGameObject* who); - void KillEntity(u16 whoID); + //void KillEntity (IGameObject* who); + void KillEntity(u16 whoID, bool bypass_actor_check = false); // Events virtual void OnEvent(NET_Packet& P, u16 type); diff --git a/src/xrGame/game_object_space.h b/src/xrGame/game_object_space.h index 9b5bdf1a8ea..549a458573b 100644 --- a/src/xrGame/game_object_space.h +++ b/src/xrGame/game_object_space.h @@ -54,18 +54,20 @@ enum ECallbackType eInvBoxItemTake, eWeaponNoAmmoAvailable, - /* avo: custom callbacks */ - // input + //AVO: custom callbacks + // Input eKeyPress, eKeyRelease, eKeyHold, eMouseMove, eMouseWheel, - // inventory + // Inventory eItemToBelt, eItemToSlot, eItemToRuck, - /* avo: end */ + // Actor + eActorBeforeDeath, + //-AVO eDummy = u32(-1), }; diff --git a/src/xrGame/script_game_object.h b/src/xrGame/script_game_object.h index 1d833616240..8fbbeb4182e 100644 --- a/src/xrGame/script_game_object.h +++ b/src/xrGame/script_game_object.h @@ -189,7 +189,7 @@ class CScriptGameObject _DECLARE_FUNCTION10(Squad, int); _DECLARE_FUNCTION10(Group, int); - void Kill(CScriptGameObject* who); + void Kill(CScriptGameObject* who, bool bypass_actor_check = false /*AVO: added for actor before death callback*/); // CEntityAlive _DECLARE_FUNCTION10(GetFOV, float); @@ -821,7 +821,8 @@ class CScriptGameObject bool isWeaponGL() const; bool isInventoryBox() const; bool IsActorOutdoors() const; - //end AVO + void SetHealthEx(float hp); + //-AVO doors::door* m_door; }; diff --git a/src/xrGame/script_game_object4.cpp b/src/xrGame/script_game_object4.cpp index 7f6d8725cdc..a29789fe772 100644 --- a/src/xrGame/script_game_object4.cpp +++ b/src/xrGame/script_game_object4.cpp @@ -368,6 +368,16 @@ void CScriptGameObject::stop_particles(LPCSTR pname, LPCSTR bone) LuaMessageType::Error, "Cant stop particles, bone [%s] is not visible now", bone); } +//AVO: directly set entity health instead of going throuhg normal health property which operates on delta +void CScriptGameObject::SetHealthEx(float hp) +{ + CEntity* obj = smart_cast(&object()); + if (!obj) return; + clamp(hp, -0.01f, 1.0f); + obj->SetfHealth(hp); +} +//-AVO + // AVO: functions for testing object class // Credits: KD //#include "Car.h" diff --git a/src/xrGame/script_game_object_script.cpp b/src/xrGame/script_game_object_script.cpp index fd477fa23d2..e14b0e8cbd5 100644 --- a/src/xrGame/script_game_object_script.cpp +++ b/src/xrGame/script_game_object_script.cpp @@ -83,18 +83,20 @@ SCRIPT_EXPORT(CScriptGameObject, (), { value("take_item_from_box", int(GameObject::eInvBoxItemTake)), value("weapon_no_ammo", int(GameObject::eWeaponNoAmmoAvailable)), - /* avo: custom callbacks */ - // input + //AVO: custom callbacks + // Input value("key_press", int(GameObject::eKeyPress)), value("key_release", int(GameObject::eKeyRelease)), value("key_hold", int(GameObject::eKeyHold)), value("mouse_move", int(GameObject::eMouseMove)), value("mouse_wheel", int(GameObject::eMouseWheel)), - // inventory + // Inventory value("item_to_belt", int(GameObject::eItemToBelt)), value("item_to_slot", int(GameObject::eItemToSlot)), value("item_to_ruck", int(GameObject::eItemToRuck)), - /* avo: end */ + // Actor + value("actor_before_death", int(GameObject::eActorBeforeDeath)), + //-AVO value("map_location_added", int(GameObject::eMapLocationAdded))], diff --git a/src/xrGame/script_game_object_script3.cpp b/src/xrGame/script_game_object_script3.cpp index f9071338685..b714c248e81 100644 --- a/src/xrGame/script_game_object_script3.cpp +++ b/src/xrGame/script_game_object_script3.cpp @@ -385,8 +385,9 @@ class_& script_register_game_object2(class_(&object()); if (!l_tpEntity) @@ -69,7 +69,7 @@ void CScriptGameObject::Kill(CScriptGameObject* who) return; } if (!l_tpEntity->AlreadyDie()) - l_tpEntity->KillEntity(who ? who->object().ID() : object().ID()); + l_tpEntity->KillEntity(who ? who->object().ID() : object().ID(), bypass_actor_check); else ai().script_engine().script_log(LuaMessageType::Error, "attempt to kill dead object %s", *object().cName()); }