Dayz Build 1.29.163047, Scripts Rev. 123548
Dayz Code Explorer by Zeroy
Loading...
Searching...
No Matches
actionskinning.c
Go to the documentation of this file.
1/*
2Example of skinning config which should be inside animal's base class:
3class Skinning
4{
5 // All classes in this scope are parsed, so they can have any name.
6 class ObtainedSteaks
7 {
8 item = "DeerSteakMeat"; // item to spawn
9 count = 10; // How many items to spawn
10 transferToolDamageCoef = 1; // Optional: How much tool's damage is transfered to item's damage.
11
12 // Make sure to have only 1 of the following quantity paramenter
13 quantity = 100; // Optional: Set item's quantity
14 quantityCoef = 1; // Optional: Set item's quantity (in coefficient)
15 quantityMinMax[] = {100, 200}; // Optional: Set item's quantity within min/max values
16 quantityMinMaxCoef[] = {0, 1}; // Optional: Set item's quantity (in coefficient) within min/max values
17 };
18};
19*/
20
22{
23 override void CreateActionComponent()
24 {
25 m_ActionData.m_ActionComponent = new CAContinuousTime(UATimeSpent.SKIN);
26 }
27}
28
30{
31 void ActionSkinning()
32 {
33 m_CallbackClass = ActionSkinningCB;
34 m_SpecialtyWeight = UASoftSkillsWeight.PRECISE_MEDIUM;
35
36 m_CommandUID = DayZPlayerConstants.CMD_ACTIONFB_ANIMALSKINNING;
37 m_StanceMask = DayZPlayerConstants.STANCEMASK_CROUCH;
38 m_FullBody = true;
39 m_Text = "#skin";
40 }
41
43 {
44 m_ConditionItem = new CCINonRuined();
45 m_ConditionTarget = new CCTCursorNoRuinCheck();
46 }
47
48 override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
49 {
50 Object targetObject = target.GetObject();
51
52 if (targetObject.CanBeSkinned() && !targetObject.IsAlive())
53 {
54 EntityAI target_EAI;
55 if (Class.CastTo(target_EAI, targetObject) && target_EAI.CanBeSkinnedWith(item))
56 return true;
57 }
58
59 return false;
60 }
61
62 // Spawns the loot according to the Skinning class in the dead agent's config
63 override void OnFinishProgressServer(ActionData action_data)
64 {
65 super.OnFinishProgressServer(action_data);
66
67 Object targetObject = action_data.m_Target.GetObject();
68
69 // Mark the body as skinned to forbid another skinning action on it
70 EntityAI body = EntityAI.Cast(targetObject);
71 body.SetAsSkinned();
72
73 MiscGameplayFunctions.RemoveAllAttachedChildrenByTypename(body, {Bolt_Base});
74
75 HandlePlayerBody(action_data);
76 SpawnItems(action_data);
77
78 if (body)
79 {
80 GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(GetGame().ObjectDelete, body);
81 }
82
83 MiscGameplayFunctions.DealAbsoluteDmg(action_data.m_MainItem, UADamageApplied.SKINNING);
84
86 moduleLifespan.UpdateBloodyHandsVisibility(action_data.m_Player, true);
87 action_data.m_Player.SetBloodyHandsPenaltyChancePerAgent(eAgents.SALMONELLA, body.GetSkinningBloodInfectionChance(eAgents.SALMONELLA));
88 }
89
90 // Spawns an organ defined in the given config
91 ItemBase CreateOrgan(PlayerBase player, vector body_pos, string item_to_spawn, string cfg_skinning_organ_class, ItemBase tool)
92 {
93 // Create item from config
94 ItemBase added_item;
95 vector posHead;
96 MiscGameplayFunctions.GetHeadBonePos(player,posHead);
97 vector posRandom = MiscGameplayFunctions.GetRandomizedPositionVerified(posHead,body_pos,UAItemsSpreadRadius.NARROW,player);
98 Class.CastTo(added_item, GetGame().CreateObjectEx(item_to_spawn, posRandom, ECE_PLACE_ON_SURFACE));
99
100 // Check if skinning is configured for this body
101 if (!added_item)
102 return null;
103
104 // Set item's quantity from config, if it's defined there.
105 float item_quantity = 0;
106 array<float> quant_min_max = new array<float>;
107 array<float> quant_min_max_coef = new array<float>;
108
109 GetGame().ConfigGetFloatArray(cfg_skinning_organ_class + "quantityMinMax", quant_min_max);
110 GetGame().ConfigGetFloatArray(cfg_skinning_organ_class + "quantityMinMaxCoef", quant_min_max_coef);
111
112 // Read config for quantity value
113 if (quant_min_max.Count() > 0)
114 {
115 float soft_skill_manipulated_value = (quant_min_max.Get(0)+ quant_min_max.Get(1)) / 2;
116 item_quantity = Math.RandomFloat(soft_skill_manipulated_value, quant_min_max.Get(1));
117 }
118
119 if (quant_min_max_coef.Count() > 0)
120 {
121 float coef = Math.RandomFloat(quant_min_max_coef.Get(0), quant_min_max_coef.Get(1));
122 item_quantity = added_item.GetQuantityMax() * coef;
123 }
124
125 if (GetGame().ConfigGetFloat(cfg_skinning_organ_class + "quantity") > 0)
126 item_quantity = g_Game.ConfigGetFloat(cfg_skinning_organ_class + "quantity");
127
128 if (GetGame().ConfigGetFloat(cfg_skinning_organ_class + "quantityCoef") > 0)
129 {
130 float coef2 = g_Game.ConfigGetFloat(cfg_skinning_organ_class + "quantityCoef");
131 item_quantity = added_item.GetQuantityMax() * coef2;
132 }
133
134 if (item_quantity > 0)
135 {
136 item_quantity = Math.Round(item_quantity);
137 added_item.SetQuantity(item_quantity, false);
138 }
139
140 // Transfer tool's damage to the item's condition
141 float item_apply_tool_damage_coef = GetGame().ConfigGetFloat(cfg_skinning_organ_class + "transferToolDamageCoef");
142
143 if (item_apply_tool_damage_coef > 0)
144 {
145 float tool_dmg_coef = 1 - tool.GetHealth01();
146 float organ_dmg_coef = tool_dmg_coef * item_apply_tool_damage_coef;
147 added_item.DecreaseHealthCoef(organ_dmg_coef);
148 }
149
150 added_item.InsertAgent(eAgents.SALMONELLA, 1);
151 return added_item;
152 }
153
154 override void OnFinishProgressClient(ActionData action_data)
155 {
156 super.OnFinishProgressClient(action_data);
157
158 if (action_data.m_Target)
159 {
160 Object target_obj = action_data.m_Target.GetObject();
161
162 if (target_obj.IsKindOf("Animal_CapreolusCapreolus") || target_obj.IsKindOf("Animal_CapreolusCapreolusF") || target_obj.IsKindOf("Animal_CervusElaphus") || target_obj.IsKindOf("Animal_CervusElaphusF"))
163 {
164 GetGame().GetAnalyticsClient().OnActionFinishedGutDeer();
165 }
166 }
167 }
168
170 void HandlePlayerBody(ActionData action_data)
171 {
172 PlayerBase body;
173 if (Class.CastTo(body,action_data.m_Target.GetObject()))
174 {
175 if (body.IsRestrained() && body.GetHumanInventory().GetEntityInHands())
176 MiscGameplayFunctions.TransformRestrainItem(body.GetHumanInventory().GetEntityInHands(), null, action_data.m_Player, body);
177
178 //Remove splint if target is wearing one
179 if (body.IsWearingSplint())
180 {
181 EntityAI entity = action_data.m_Player.SpawnEntityOnGroundOnCursorDir("Splint", 0.5);
182 ItemBase newItem = ItemBase.Cast(entity);
183 EntityAI attachment = body.GetItemOnSlot("Splint_Right");
184 if (attachment && attachment.GetType() == "Splint_Applied")
185 {
186 if (newItem)
187 {
188 MiscGameplayFunctions.TransferItemProperties(attachment, newItem);
189 //Lower health level of splint after use
190 if (newItem.GetHealthLevel() < 4)
191 {
192 int newDmgLevel = newItem.GetHealthLevel() + 1;
193 float max = newItem.GetMaxHealth("", "");
194
195 switch (newDmgLevel)
196 {
198 newItem.SetHealth("", "", max * GameConstants.DAMAGE_BADLY_DAMAGED_VALUE);
199 break;
200
202 newItem.SetHealth("", "", max * GameConstants.DAMAGE_DAMAGED_VALUE);
203 break;
204
206 newItem.SetHealth("", "", max * GameConstants.DAMAGE_WORN_VALUE);
207 break;
208
210 newItem.SetHealth("", "", max * GameConstants.DAMAGE_RUINED_VALUE);
211 break;
212
213 default:
214 break;
215 }
216 }
217 }
218
219 attachment.Delete();
220 }
221 }
222
223 int deadBodyLifetime;
224 if (GetCEApi())
225 {
226 deadBodyLifetime = GetCEApi().GetCEGlobalInt("CleanupLifetimeDeadPlayer");
227 if (deadBodyLifetime <= 0)
228 deadBodyLifetime = 3600;
229 }
230
231 DropInventoryItems(body,deadBodyLifetime);
232 }
233 }
234
235 void DropInventoryItems(PlayerBase body, float newLifetime)
236 {
237 array<EntityAI> children = new array<EntityAI>;
238 body.GetInventory().EnumerateInventory(InventoryTraversalType.LEVELORDER, children);
239 foreach (EntityAI child : children)
240 {
241 if (child)
242 {
243 child.SetLifetime(newLifetime);
244 body.GetInventory().DropEntity(InventoryMode.SERVER, body, child);
245 }
246 }
247 }
248
249 void SpawnItems(ActionData action_data)
250 {
251 EntityAI body = EntityAI.Cast(action_data.m_Target.GetObject());
252
253 // Get config path to the animal
254 string cfgAnimalClassPath = "cfgVehicles " + body.GetType() + " " + "Skinning ";
255 vector bodyPosition = body.GetPosition();
256
257 if (!g_Game.ConfigIsExisting(cfgAnimalClassPath))
258 {
259 Debug.Log("Failed to find class 'Skinning' in the config of: " + body.GetType());
260 return;
261 }
262
263 // Getting item type from the config
264 int childCount = g_Game.ConfigGetChildrenCount(cfgAnimalClassPath);
265
266 string itemToSpawn;
267 string cfgSkinningOrganClass;
268 // Parsing of the 'Skinning' class in the config of the dead body
269 for (int i1 = 0; i1 < childCount; i1++)
270 {
271 // To make configuration as convenient as possible, all classes are parsed and parameters are read
272 g_Game.ConfigGetChildName(cfgAnimalClassPath, i1, cfgSkinningOrganClass); // out cfgSkinningOrganClass
273 cfgSkinningOrganClass = cfgAnimalClassPath + cfgSkinningOrganClass + " ";
274 g_Game.ConfigGetText(cfgSkinningOrganClass + "item", itemToSpawn); // out itemToSpawn
275
276 if (itemToSpawn != "") // Makes sure to ignore incompatible parameters in the Skinning class of the agent
277 {
278 // Spawning items in action_data.m_Player's inventory
279 int itemSpawnCount = g_Game.ConfigGetInt(cfgSkinningOrganClass + "count");
280
281 array<string> itemZones = new array<string>;
282 array<float> itemCount = new array<float>;
283 float zoneDmg = 0;
284
285 GetGame().ConfigGetTextArray(cfgSkinningOrganClass + "itemZones", itemZones);
286 GetGame().ConfigGetFloatArray(cfgSkinningOrganClass + "countByZone", itemCount);
287 float transferedPartDmgCoef = GetGame().ConfigGetFloat(cfgSkinningOrganClass + "transferPartDamageCoef");
288
289 if (itemCount.Count() > 0)
290 {
291 itemSpawnCount = 0;
292 for (int z = 0; z < itemZones.Count(); z++)
293 {
294 zoneDmg = body.GetHealth01(itemZones[z], "Health");
295 zoneDmg *= itemCount[z]; //just re-using variable
296 itemSpawnCount += Math.Floor(zoneDmg);
297 }
298 }
299
300 if (transferedPartDmgCoef > 0 && itemSpawnCount <= 0) // Special behavior for headdress
301 itemSpawnCount = 1;
302
303 for (int i2 = 0; i2 < itemSpawnCount; i2++)
304 {
305 ItemBase spawnResult = CreateOrgan(action_data.m_Player, bodyPosition, itemToSpawn, cfgSkinningOrganClass, action_data.m_MainItem);
306 if (!spawnResult)
307 continue;
308
309 // Damage spawned result item based on the average health value of the body part
310 // It only works if the "transferPartDamageCoef" value in the config is higher than 0 and result item is from type Headdress
311 if (transferedPartDmgCoef > 0)
312 {
313 float partHealth = 0;
314 float partMaxHealth = 0;
315 for (int z2 = 0; z2 < itemZones.Count(); z2++)
316 {
317 partHealth = body.GetHealth(itemZones[z2], "Health");
318 partMaxHealth = body.GetMaxHealth(itemZones[z2], "Health");
319 break;
320 }
321
322 if (partMaxHealth > 0)
323 {
324 float itemMaxHealth = spawnResult.GetMaxHealth("", "Health");
325 float partHealthPercent = (partHealth / partMaxHealth) * 100;
326 float itemHealth = (itemMaxHealth / 100) * partHealthPercent;
327
328 if (transferedPartDmgCoef > 1) // Makes sure to adjust incompatible parameter in the Skinning class of the agent
329 transferedPartDmgCoef = 1;
330
331 float itemHealthCoef = itemHealth * transferedPartDmgCoef;
332 spawnResult.SetHealth("", "Health", itemHealthCoef);
333 }
334 }
335
336 //Damage pelts based on the average values on itemZones
337 //It only works if the "quantityCoef" in the config is more than 0
338 float qtCoeff = GetGame().ConfigGetFloat(cfgSkinningOrganClass + "quantityCoef");
339 if (qtCoeff > 0)
340 {
341 float avgDmgZones = 0;
342 for (int c2 = 0; c2 < itemZones.Count(); c2++)
343 {
344 avgDmgZones += body.GetHealth01(itemZones[c2], "Health");
345 }
346
347 avgDmgZones = avgDmgZones/itemZones.Count(); // Evaluate the average Health
348 spawnResult.SetHealth01("","", avgDmgZones);
349 }
350
351 // inherit temperature
352 if (body.CanHaveTemperature() && spawnResult.CanHaveTemperature())
353 {
354 spawnResult.SetTemperatureDirect(body.GetTemperature());
355 spawnResult.SetFrozen(body.GetIsFrozen());
356 }
357
358 // handle fat/guts from human bodies
359 if ((itemToSpawn == "Lard") || (itemToSpawn == "Guts"))
360 {
361 if (body.IsKindOf("SurvivorBase"))
362 {
363 spawnResult.InsertAgent(eAgents.BRAIN, 1);
364 }
365 }
366 }
367 }
368 }
369 }
370
371 //DEPRECATED
373 {
374 return body_pos + Vector(Math.RandomFloat01() - 0.5, 0, Math.RandomFloat01() - 0.5);
375 }
376}
InventoryMode
NOTE: PREDICTIVE is not to be used at all in multiplayer.
Definition inventory.c:22
int m_CommandUID
Definition actionbase.c:31
int m_StanceMask
Definition actionbase.c:33
ActionBase ActionData
Definition actionbase.c:30
void DropInventoryItems(PlayerBase body, float newLifetime)
vector GetRandomPos(vector body_pos)
void HandlePlayerBody(ActionData action_data)
This section drops all clothes (and attachments) from the dead player before deleting their body.
ActionSkinningCB ActionContinuousBaseCB ActionSkinning()
ItemBase CreateOrgan(PlayerBase player, vector body_pos, string item_to_spawn, string cfg_skinning_organ_class, ItemBase tool)
class ActionTargets ActionTarget
proto native CEApi GetCEApi()
Get the CE API.
const int ECE_PLACE_ON_SURFACE
ActionData m_ActionData
void CreateConditionComponents()
Definition actionbase.c:236
void OnFinishProgressServer(ActionData action_data)
void OnFinishProgressClient(ActionData action_data)
override void CreateActionComponent()
override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
Super root of all classes in Enforce script.
Definition enscript.c:11
Definition debug.c:2
static void Log(string message=LOG_DEFAULT, string plugin=LOG_DEFAULT, string author=LOG_DEFAULT, string label=LOG_DEFAULT, string entity=LOG_DEFAULT)
Prints debug message with normal prio.
Definition debug.c:182
override bool SetQuantity(float value, bool destroy_config=true, bool destroy_forced=false, bool allow_client=false, bool clamp_to_stack_max=true)
Definition enmath.c:7
const float SKINNING
const float SKIN
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
void SpawnItems()
DayZGame g_Game
Definition dayzgame.c:3942
DayZPlayerConstants
defined in C++
Definition dayzplayer.c:602
eAgents
Definition eagents.c:3
InventoryTraversalType
tree traversal type, for more see http://en.wikipedia.org/wiki/Tree_traversal
Definition gameplay.c:6
DayZGame GetGame()
Definition gameplay.c:636
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
const float DAMAGE_RUINED_VALUE
Definition constants.c:867
const float DAMAGE_DAMAGED_VALUE
Definition constants.c:865
const float DAMAGE_BADLY_DAMAGED_VALUE
Definition constants.c:866
const float DAMAGE_WORN_VALUE
Definition constants.c:864
const int STATE_RUINED
Definition constants.c:851
const int STATE_BADLY_DAMAGED
Definition constants.c:852
const int STATE_DAMAGED
Definition constants.c:853
const int STATE_WORN
Definition constants.c:854
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
static proto float Round(float f)
Returns mathematical round of value.
static proto float RandomFloat(float min, float max)
Returns a random float number between and min[inclusive] and max[exclusive].
static float RandomFloat01()
Returns a random float number between and min [inclusive] and max [inclusive].
Definition enmath.c:126
static proto float Floor(float f)
Returns floor of value.
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
void PluginLifespan()
PluginBase GetPlugin(typename plugin_type)