geekm0nkey

[Release] Ducks of War

25 posts in this topic

Demo: (yes the video doesn't show the body being removed, was made before that was fixed.)

Another contribution to the PVP mod community. Introducing Ducks of War... What this mod does is add the option to "Claim a Trophy" from a PVP killed player.  The trophy in this case happens to be a rubber ducky. Which they can collect and sell at the traders. You adjust the value of the duck in the code provided below. Here are the conditions.

  • Body must be a player (no NPC or Zombies)
  • Player must be killed as a direct result of PVP, no bambis, team-kills, crashes, accidents or suicides.
  • Once trophy claimed, body will be removed. (so collect gear FIRST!) *Thanks to StokesMagee

Installation:

Create the file dow_claimtrophy.sqf and put it somewhere in your mission folder.. For mine i use the folder addons.

Spoiler

/* --------------------------------------------------
 * Ducks of war mod
 * Created by Geekm0nkey for Arma 3 Exile.
 * Copyright 2018, Geekm0nkey, All rights reserved.
 * --------------------------------------------------
 */
 
private["_target","_victim","_killer","_killType","_credit","_reward"];

_target     = _this select 0;
_victim     = _target getVariable["ExileName", "-unknown-"];
_killer     = _target getVariable["DOWGV_killer", 0];
_killType     = _target getVariable["DOWGV_killType", 0];

if (_killer == name player) then
{
    _credit = "your";
}else
{
    _credit = "someone else's";
};

["SuccessTitleAndText", ["DOW: Trophy search!", format["looking for a trophy from %1 kill.", _credit]]] call ExileClient_gui_toaster_addTemplateToast;

switch (_killType) do
{
    default
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        uisleep 10;
        ["ErrorTitleAndText", ["DOW: Trophy failed!", format["No trophy can be collected at this time from %1.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
    case 3:
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        uisleep 10;
        ["ErrorTitleAndText", ["DOW: Trophy failed!", format["%1 was killed in an accident! Cannot collect from crash test dummies.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
    case 4:
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        uisleep 10;
        ["ErrorTitleAndText", ["DOW: Trophy failed!", format["%1 was killed by NPC! Cannot collect from AI kills.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
    case 5:
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        uisleep 10;
        ["ErrorTitleAndText", ["DOW: Trophy failed!", format["%1 was team-killed! Cannot collect from dishonorable kills.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
    case 6:
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        uisleep 10;
        ["ErrorTitleAndText", ["DOW: Trophy failed!", format["%1 was a BAMBI! Cannot collect from fresh spawns.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
    case 7:
    {
        player playMove "AinvPknlMstpSnonWnonDr_medic1";
        _target setVariable["DOWGV_killType", 0];
        player action ["hideBody", _target];
        uisleep 10;
        deleteVehicle _target;
        _target setPos [0,0,0];
        _reward = createVehicle [ "WeaponHolderSimulated", player modelToWorld [0,2,.5], [], 0, "CAN_COLLIDE" ];  
        _reward addMagazineCargoGlobal ["Exile_item_RubberDuck", 1];
        ["SuccessTitleAndText", ["DOW: Trophy collected!", format["You have successfully claimed your trophy of a rubber ducky from %1.", _victim]]] call ExileClient_gui_toaster_addTemplateToast;
    };
};

 

Next Step:

Edit the file initPlayerLocal.sqf if you have it, or make one.. And add this near the top. Make sure to adjust the folder to match yours.

Spoiler

// Ducks of war mod
DOW_FN_ClaimTrophy = compileFinal preprocessFileLineNumbers "addons\dow_claimtrophy.sqf";

Next Step:

Edit the file config.cpp and add the following... Find "class Player" >> "class Actions" look for "Identify Body" put this code below that block of code so that it looks like the following. Do not duplicate the identify body section, this is just an example of how it should look.

Spoiler

class Identify: ExileAbstractAction
            {
                title = "Identify Body";
                condition = "!(alive ExileClientInteractionObject)";
                action = "_this call ExileClient_object_player_identifyBody";
            };
           
            // Ducks of war mod
            class Trophy: ExileAbstractAction
            {
                title = "Claim Trophy";
                condition = "!(alive ExileClientInteractionObject)";
                action = "_this call DOW_FN_ClaimTrophy";
            };

Next Step:

By now, you should have an overwrite created for a killfeed... If you don't, wouldn't hurt to create one. I will provide a copy of mine for you but you only need the 2 lines that pertain to this mod to be added to yours if you already have one. *Thanks to Kuplion.

Spoiler

/**
 * ExileServer_object_player_event_onMpKilled
 *
 * Exile Mod
 * exile.majormittens.co.uk
 * © 2015 Exile Mod Team
 *
 * Modified by [FPS]kuplion - www.friendlyplayershooting.com
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 */
 
private["_victim","_killer","_countDeath","_countKill","_killSummary","_killingPlayer","_killType","_oldVictimRespect","_newVictimRespect","_oldKillerRespect","_newKillerRespect","_systemChat","_modifyVictimRespect","_respectLoss","_perks","_minRespectTransfer","_respectTransfer","_perkNames","_killerStatsNeedUpdate","_newKillerFrags","_victimStatsNeedUpdate","_newVictimDeaths","_victimPosition"];
_victim = _this select 0;
_killer = _this select 1;
//_instigator = _this select 2; // 1.0.3 Seems to be bugged
if (!isServer || hasInterface || isNull _victim) exitWith {};
_victim setVariable ["ExileDiedAt", time];
if !(isPlayer _victim) exitWith {};
_victim setVariable ["ExileIsDead", true];
_victim setVariable ["ExileName", name _victim, true];
_countDeath = false;
_countKill = false;
_killSummary = [];
_killingPlayer = _killer call ExileServer_util_getFragKiller;
_killType = [_victim, _killer, _killingPlayer] call ExileServer_util_getFragType; // 1.0.2 files as a temp fix
//_killType = [_victim, _killer, _killingPlayer, _instigator] call ExileServer_util_getFragType; // 1.0.3 Seems to be bugged
_oldVictimRespect = _victim getVariable ["ExileScore", 0];
_newVictimRespect = _oldVictimRespect;
_oldKillerRespect = 0;
if !(isNull _killingPlayer) then
{
    _oldKillerRespect = _killingPlayer getVariable ["ExileScore", 0];
};
_newKillerRespect = _oldKillerRespect;

// Ducks of war mod
_victim setVariable["DOWGV_killer", name _killingPlayer, 0];
_victim setVariable["DOWGV_killType", _killType, 0];

switch (_killType) do
{
    default
    {
        _unknownReasons =
        [
            "%1 died because... Arma.",
            "%1 died because the universe hates him.",
            "%1 died a mysterious death.",
            "%1 died and nobody knows why.",
            "%1 died because that's why.",
            "%1 died because %1 was very unlucky.",
            "%1 died due to Arma bugs and is probably very salty right now.",
            "%1 died an awkward death.",
            "%1 died. Yes, %1 is dead. Like really dead-dead."
        ];
        _countDeath = true;
        _systemChat = format [selectRandom _unknownReasons, name _victim];
        _newVictimRespect = _oldVictimRespect - round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "unlucky")));
    };
    case 1:
    {
        private["_zombieKill"];
        _victimPosition = position _victim;
        _bystanders = _victimPosition nearEntities ['Man',5];
        _zombieKill = false;
        {
            _zombieKill = getText(configFile >> 'CfgVehicles' >> typeOf _x >> 'author') isEqualTo 'Ryan';
        } forEach _bystanders;
       
        if(_zombieKill) then
        {
        _countDeath = true;
        _modifyVictimRespect = true;
        _zombieDeath = selectRandom ["was killed", "was eaten"]; //Add more messages here to change the killed text
        _systemChat = format ["%1 %2 by a zombie!", name _victim, _zombieDeath];
        _newVictimRespect = _oldVictimRespect - round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "suicide")));
        }
        else
        {
       
        _countDeath = true;
        _modifyVictimRespect = true;
        _systemChat = format ["%1 commited suicide!", name _victim];
        _newVictimRespect = _oldVictimRespect - round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "suicide")));
        };
    };
    case 2:
    {
        _countDeath = true;
        _countKill = false;
        _systemChat = format ["%1 died while playing Russian Roulette!", name _victim];
        _newVictimRespect = _oldVictimRespect;
        _victim call ExileServer_system_russianRoulette_event_onPlayerDied;
    };
    case 3:
    {
        _countDeath = true;
        _countKill = false;
        _systemChat = format ["%1 crashed and died!", name _victim];
        _newVictimRespect = _oldVictimRespect - round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "crash")));
    };
    case 4:
    {
        _countDeath = true;
        _countKill = false;
        _npcDeath = selectRandom ["was killed", "was murdered"]; //Add more messages here to change the killed text
        _systemChat = format ["%1 %2 by an NPC!", name _victim, _npcDeath];
        _newVictimRespect = _oldVictimRespect - round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "npc")));
    };
    case 5:
    {
        _countDeath = false;
        _countKill = false;
        _systemChat = format ["%1 was team-killed by %2!", name _victim, name _killingPlayer];
        _respectLoss = round ((abs _oldKillerRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "friendyFire")));
        _newKillerRespect = _oldKillerRespect - _respectLoss;
        _killSummary pushBack ["FRIENDLY FIRE", -1 * _respectLoss];
    };
    case 6:
    {
        _countDeath = false;
        _countKill = false;
        _systemChat = format ["%1 was killed by %2! (BAMBI SLAYER)", name _victim, name _killingPlayer];
        _respectLoss = round ((abs _oldKillerRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "bambiKill")));
        _newKillerRespect = _oldKillerRespect - _respectLoss;
        _killSummary pushBack ["BAMBI SLAYER", -1 * _respectLoss];
    };
    case 7:
    {
        private["_weapon","_weaponDisplayName","_weaponScope","_weaponScopeDisplayName","_vehicle"];
        _countDeath = true;
        _countKill = true;
        _perks = [_victim, _killer, _killingPlayer] call ExileServer_util_getFragPerks;
        _minRespectTransfer = getNumber (configFile >> "CfgSettings" >> "Respect" >> "minRespectTransfer");
        _respectTransfer = round ((abs _oldVictimRespect) / 100 * (getNumber (configFile >> "CfgSettings" >> "Respect" >> "Percentages" >> "frag")));


       
        _weapon = currentWeapon _killer;
        _weaponDisplayName = getText (configfile >> "CfgWeapons" >> _weapon >> "displayName");
               
        if !((vehicle _killer) isEqualTo _killer) then
        {
            _weapon = vehicle _killer weaponsTurret (assignedVehicleRole _killer select 1);
            _weaponDisplayName = getText (configfile >> "CfgWeapons" >> _weapon select 0 >> "displayName");
        };
       
        _weaponScope = "";
        _weaponScopeDisplayName = "Iron Sights";
        if ((vehicle _killer) isEqualTo _killer) then
        {
            _weaponScope = (_killer weaponAccessories (currentWeapon _killer)) select 2;
            if !(_weaponScope isEqualTo "") then
            {
                _weaponScopeDisplayName = getText (configfile >> "CfgWeapons" >> _weaponScope >> "displayName");
            };
        };
       
        if (_respectTransfer < _minRespectTransfer) then
        {
            _respectTransfer = _minRespectTransfer;
        };
        _newVictimRespect = _oldVictimRespect - _respectTransfer;
        _newKillerRespect = _oldKillerRespect + _respectTransfer;
        _killSummary pushBack ["ENEMY FRAGGED", _respectTransfer];
        if (_perks isEqualTo []) then
        {
            if !((vehicle _killer) isEqualTo _killer) then
            {
            _systemChat = format ["%1 was killed by %2", name _victim, name _killingPlayer];
            }
            else
            {
            _systemChat = format ["%1 was killed by %2 with a %3 (%4)!", name _victim, name _killingPlayer, _weaponDisplayName, _weaponScopeDisplayName];
            };
           
        }
        else
        {
            if !((vehicle _killer) isEqualTo _killer) then
            {
            _perkNames = [];
            {
                _perkNames pushBack (_x select 0);
                _killSummary pushBack _x;
                _newKillerRespect = _newKillerRespect + (_x select 1);
            }
            forEach _perks;
            _systemChat = format ["%1 was killed by %2! (%3)", name _victim, name _killingPlayer, _perkNames joinString ", "];
            }           
            else
            {
            _perkNames = [];
            {
                _perkNames pushBack (_x select 0);
                _killSummary pushBack _x;
                _newKillerRespect = _newKillerRespect + (_x select 1);
            }
            forEach _perks;
            _systemChat = format ["%1 was killed by %2 with a %3 (%4)! (%5)", name _victim, name _killingPlayer, _weaponDisplayName, _weaponScopeDisplayName, _perkNames joinString ", "];
            };
           
        };
    };
};
if !(isNull _killingPlayer) then
{
    if !(_killSummary isEqualTo []) then
    {   
        [_killingPlayer, "showFragRequest", [_killSummary]] call ExileServer_system_network_send_to;
    };
};
if !(isNull _killingPlayer) then
{
    _killerStatsNeedUpdate = false;
    if (_countKill) then
    {
        _newKillerFrags = _killingPlayer getVariable ["ExileKills", 0];
        _newKillerFrags = _newKillerFrags + 1;
        _killerStatsNeedUpdate = true;
        _killingPlayer setVariable ["ExileKills", _newKillerFrags];
        format["addAccountKill:%1", getPlayerUID _killingPlayer] call ExileServer_system_database_query_fireAndForget;
    };
    if !(_newKillerRespect isEqualTo _oldKillerRespect) then
    {
        _killingPlayer setVariable ["ExileScore", _newKillerRespect];
        _killerStatsNeedUpdate = true;
        format["setAccountScore:%1:%2", _newKillerRespect, getPlayerUID _killingPlayer] call ExileServer_system_database_query_fireAndForget;
    };
    if (_killerStatsNeedUpdate) then
    {
        _killingPlayer call ExileServer_object_player_sendStatsUpdate;
    };
};
_victimStatsNeedUpdate = false;
if (_countDeath) then
{
    _newVictimDeaths = _victim getVariable ["ExileDeaths", 0];
    _newVictimDeaths = _newVictimDeaths + 1;
    _victim setVariable ["ExileDeaths", _newVictimDeaths];
    _victimStatsNeedUpdate = true;
    format["addAccountDeath:%1", getPlayerUID _victim] call ExileServer_system_database_query_fireAndForget;
};
if !(_newVictimRespect isEqualTo _oldVictimRespect) then
{
    _victim setVariable ["ExileScore", _newVictimRespect];
    _victimStatsNeedUpdate = true;
    format["setAccountScore:%1:%2", _newVictimRespect, getPlayerUID _victim] call ExileServer_system_database_query_fireAndForget;
};
if (_victimStatsNeedUpdate) then
{
    _victim call ExileServer_object_player_sendStatsUpdate;
};
if ((vehicle _victim) isEqualTo _victim) then
{
    if !(underwater _victim) then
    {
        if !(_victim call ExileClient_util_world_isInTraderZone) then
        {
            _victim call ExileServer_object_flies_spawn;
        };
    };
};
if !(_systemChat isEqualTo "") then
{
    if ((getNumber (configFile >> "CfgSettings" >> "KillFeed" >> "showKillFeed")) isEqualTo 1) then
    {
        ["systemChatRequest", [_systemChat]] call ExileServer_system_network_send_broadcast;
    };
};
if !(_systemChat isEqualTo "") then
{
    if ((getNumber (configFile >> "CfgSettings" >> "Logging" >> "deathLogging")) isEqualTo 1) then
    {
        "extDB2" callExtension format["1:DEATH:%1", _systemChat];
    };
};
_victimPosition = getPos _victim;
format["insertPlayerHistory:%1:%2:%3:%4:%5", getPlayerUID _victim, name _victim, _victimPosition select 0, _victimPosition select 1, _victimPosition select 2] call ExileServer_system_database_query_fireAndForget;
format["deletePlayer:%1", _victim getVariable ["ExileDatabaseId", -1]] call ExileServer_system_database_query_fireAndForget;
true

or just the lines in question, which need to be added below where _killType is defined.

Spoiler

// Ducks of war mod
_victim setVariable["DOWGV_killer", name _killingPlayer, 0];
_victim setVariable["DOWGV_killType", _killType, 0];

Last Step:

You need to add the duck to the trader data so that the player can sell it. (if you already have the duck, it will need to be removed as this is the trophy item) You add this in the config.cpp or if using the easy trader mod, in the ExileItemsList.sqf as.

Spoiler

class Exile_item_RubberDuck                { quality = 1; price = 10000; sellPrice = 10000; };

Make the price and sellprice the same.

And your done... Hope you enjoy.

Edited by geekm0nkey
Improved dead body handling.
  • Like 6

Share this post


Link to post
Share on other sites

This reminds me of Call of Duty where you need to get to the body before you can get points.

Great work man! Now those ducks finally have a use! And install instructions are really clear!

Really appreciate you releasing content on ExileMod!

  • Like 1

Share this post


Link to post
Share on other sites
Advertisement

Update: Be aware that I need to add a function or server side script for clean up.. It would seem, that from the players point of view all works well. But from other players bodies are not cleaned up and exploitation is possible..

Share this post


Link to post
Share on other sites

Updated original post... Code has been fixed, should no longer be an issue with being able to access the person more than once.. After the trophy is claimed and body cleaned up, it is them moved off map.

Share this post


Link to post
Share on other sites

I didn't read completely. Already using ducks. To use other mods with ducks, I have to change the classnames in the other mods to match this reference to the duck, correct?

PS. Nice work, as usual! Thanks for all you do!

Edited by [XIII]Bujinkan

Share this post


Link to post
Share on other sites

Need to copy the code from the first post and overwrite the code in dow_claimtrophy.sqf file. Fixes the issue where the body doesn't actually disappear for other players.

No problem.. And thank you.

Edited by geekm0nkey

Share this post


Link to post
Share on other sites

Hi on the step where it says you should have a kill feed by now, guess what i dont! So i copy and paste that kill feed file of yours and what am i naming it?  ExileServer_object_player_event_onMpKilled ???? and where do i place this file just in my mission pbo?

cheers!

Share this post


Link to post
Share on other sites
Advertisement

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.