PDA

View Full Version : Rebuilding the CoD4MoD



IzNoGoD
1st November 2012, 19:56
Hey all

Currently Im rebuilding the CoD4MoD.
Will probably continue until bored.

Rebuilding it with a modular function system.

Code:



init()
{
level.functions = [];
level.functions["onconnect"] = [];
level.functions["onspawn_once"] = [];
level.functions["onspawn_continuous"] = [];
level.functions["onplayerdamage"] = [];
level.functions["onplayerkilled"] = [];

add_functions();

thread waitforplayerconnect();
}

add_functions()
{
maps\mp\izno\_assists::init();
}

waitforplayerconnect()
{
while(true)
{
level waittill("connecting",player);
player.izno = [];
for(i = 0; i < level.functions["onconnect"].size; i++)
{
player [[level.functions["onconnect"][i]]]();
}
player thread waitforspawn();
}
}

waitforspawn()
{
self endon("disconnect");
while(true)
{
self waittill("spawned_player");
for(i = 0; i < level.functions["onspawned_once"].size; i++)
{
self [[level.functions["onspawned_once"][i]]]();
}
self thread while_alive();
}
}

while_alive()
{
while(isdefined(self) && isdefined(self.sessionstate) && self.sessionstate == "playing")
{
for(i = 0; i < level.functions["onspawned_continuous"].size; i++)
{
self [[level.functions["onspawned_continuous"][i]]]();
}
wait 0.05;
}
}

Callback_PlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset)
{
for(i = 0; i < level.functions["onplayerdamage"].size; i++)
{
self [[level.functions["onplayerdamage"][i]]](eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset);
}
self [[level.Callback_PlayerDamage]](eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset);
}

Callback_PlayerKilled(eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration)
{
for(i = 0; i < level.functions["onplayerkilled"].size; i++)
{
self [[level.functions["onplayerkilled"][i]]](eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration);
}
self [[level.Callback_PlayerKilled]](eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration);
}

And


#include maps\mp\_util;

//assists: store in player's array
//go over 64 items in said array, as players might disconnect during the assist-array building
//if not found, find nearest open spot in said array
//array is self.izno["assists"][].
//store damage done by said player in self.izno["assists_damage"][]
//init both arrays on playerconnect, reset on full health and on playerspawn().


init()
{
Settings();
level.functions["onconnect"][level.functions["onconnect_once"].size] = ::onconnect_once;
level.functions["onspawn_once"][level.functions["onspawn_once"].size] = ::onspawn_once;
level.functions["onspawn_continuous"][level.functions["onspawn_continuous"].size] = ::onspawn_continuous;
level.functions["onplayerdamage"][level.functions["onplayerdamage"].size] = ::onplayerdamage;
level.functions["onplayerkilled"][level.functions["onplayerkilled"].size] = ::onplayerkilled;
}

Settings()
{
level.scorebonus = [];
level.scorebonus["assist"] = 2;
level.scorebonus["kill"] = 10;

level.moneybonus = [];'
level.moneybonus["assist"] = 2;
level.moneybonus["kill"] = 2;

level.xpbonus = [];
level.xpbonus["assist"] = 2;
level.xpbonus["kill"] = 10;

level.moneybonus = [];
level.moneybonus["assist"] = 2;
level.moneybonus["kill"] = 10;
}

onconnect_once()
{
self.izno["assists"] = [];
self.izno["assists_damage"] = [];
}

onspawn_once()
{
self.izno["assists"] = [];
}

onspawn_continuous()
{
if(self.health >= self.maxhealth)
{
self.izno["assists"] = []; //no need to reset self.izno["assists_damage"] as it is fixed in the callback_playerdamage anyway.
}
}

onplayerdamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset)
{
if(isdefined(eAttacker) && isplayer(eAttacker))
{
save_here = -1;
for(i = 0; i < 64; i++)
{
if(!isdefined(self.izno["assists"][i]) && save_here == -1)
{
save_here = i;
self.izno["assists_damage"][i] = 0;
}
else if(self.izno["assists"][i] == eAttacker)
{
save_here = i;
break;
}
}
if(save_here != -1)
{
self.izno["assists_damage"][save_here] += iDamage;
self.izno["asists"][save_here] = eAttacker;
}
}
}

onplayerkilled(eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration)
{
for(i = 0; i < 64; i++)
{
if(isdefined(self.izno["assists"][i]) && (!isdefined(eAttacker) || !isplayer(eAttacker) || eAttacker != self.izno["assists"][i]))
{
self.izno["assists"][i].score += level.scorebonus["assist"];
self.izno["assists"][i] AddStat("money", level.moneybonus["assist"]);
self.izno["assists"][i] AddStat("xp", level.xpbonus["assist"]);
//self.izno["assists"][i] updatedamagefeedback(); //not the right name i guess
}
}
if(isdefined(eAttacker) && isplayer(eAttacker) && self != eAttacker)
{
eAttacker.score += level.scorebonus["kill"] - 1; //-1 for the normal Callback_PlayerKilled already adds one
//does NOT handle teamkills well. Disable friendlyfire as it is annoying anyway.
eAttacker AddStat("money", level.moneybonus["kill"]);
eAttacker AddStat("xp", level.xpbonus["kill");
}
}

So, what do you all think?
Will this be useful to you in a future project too, or couldnt you care less?

kung foo man
2nd November 2012, 01:33
Usefull for not adding all the same logic over and over again :D

On the other side, i like to write this kind of things directly in the maps/mp/gametypes/$gametype.gsc, for the case of manipulating the flow of some hooked function:



if (sMeansOfDeath == "MOD_FALLING")
return;


So in the end, i would end up with different ways of manipulating the same function, which could become confusing.

But for functions shared between mods, its fast and easy to integrate them :)

Tally
2nd November 2012, 16:25
It's right and proper to try to eliminate as many script variables (wait, waittill, endon, etc) as possible. The stock game files have far too many of them as it is.This looks like a good way to manage multiple game events. It uses callbacks, which eliminates the need for script variables. So, it gets my thumbs up!