PDA

View Full Version : [Killcam] Nade Killcam



IzNoGoD
4th December 2014, 20:44
Here is a nice piece of code that will add nadetracking to your killcam - see http://social.xfire.com/video/62f7a3

Edit: This code works WITHOUT libcod, on any vanilla cod2 install (although only tested on 1.3)

Modify your _killcam.gsc until it looks like this:


init()
{
precacheString(&"MP_KILLCAM");
precacheString(&"PLATFORM_PRESS_TO_SKIP");
precacheString(&"PLATFORM_PRESS_TO_RESPAWN");
precacheShader("black");
//izno: added following 2 lines as precache stuff
precachemodel("xmodel/weapon_potato");
precachemodel("xmodel/prop_barrel_benzin");

killcam = getCvar("scr_killcam");
if(killcam == "") // Kill cam
killcam = "1";
setCvar("scr_killcam", killcam, true);
level.killcam = getCvarInt("scr_killcam");

if(level.killcam > 0)
setarchive(true);
thread maps\mp\gametypes\_nadekillcam::init(); //izno: initialize the nadetracker
for(;;)
{
updateKillcamSettings();
wait 1;
}
}

updateKillcamSettings()
{
killcam = getCvarInt("scr_killcam");
if(level.killcam != killcam)
{
level.killcam = getCvarInt("scr_killcam");
if((level.killcam > 0) || (getCvarInt("g_antilag") > 0))
setarchive(true);
else
setarchive(false);
}
}

killcam(attackerNum, delay, offsetTime, respawn, nade) //izno: modified function definition by adding nade as an input variable
{
self endon("spawned");

// killcam
if(attackerNum < 0)
return;

self.sessionstate = "spectator";
self.spectatorclient = attackerNum;
self.archivetime = delay + 7;
self.psoffsettime = offsetTime;

// ignore spectate permissions
self allowSpectateTeam("allies", true);
self allowSpectateTeam("axis", true);
self allowSpectateTeam("freelook", true);
self allowSpectateTeam("none", true);

// wait till the next server frame to allow code a chance to update archivetime if it needs trimming
wait 0.05;

if(self.archivetime <= delay)
{
self.sessionstate = "dead";
self.spectatorclient = -1;
self.archivetime = 0;
self.psoffsettime = 0;

return;
}

self.killcam = true;
//izno: added the following 2 lines for nade-killcam purposes
if(isdefined(nade))
self thread donadefollow(nade);

if(!level.splitscreen && !isdefined(self.kc_topbar))
{
self.kc_topbar = newClientHudElem(self);
self.kc_topbar.archived = false;
self.kc_topbar.x = 0;
self.kc_topbar.y = 0;
self.kc_topbar.horzAlign = "fullscreen";
self.kc_topbar.vertAlign = "fullscreen";
self.kc_topbar.alpha = 0.5;
self.kc_topbar setShader("black", 640, 112);
}

if(!level.splitscreen && !isdefined(self.kc_bottombar))
{
self.kc_bottombar = newClientHudElem(self);
self.kc_bottombar.archived = false;
self.kc_bottombar.x = 0;
self.kc_bottombar.y = 368;
self.kc_bottombar.horzAlign = "fullscreen";
self.kc_bottombar.vertAlign = "fullscreen";
self.kc_bottombar.alpha = 0.5;
self.kc_bottombar setShader("black", 640, 112);
}

if(!isdefined(self.kc_title))
{
self.kc_title = newClientHudElem(self);
self.kc_title.archived = false;
self.kc_title.x = 0;
self.kc_title.alignX = "center";
self.kc_title.alignY = "middle";
self.kc_title.horzAlign = "center_safearea";
self.kc_title.vertAlign = "top";
self.kc_title.sort = 1; // force to draw after the bars
self.kc_title.fontScale = 3.5;

if(level.splitscreen)
self.kc_title.y = 22;
else
self.kc_title.y = 30;
}
self.kc_title setText(&"MP_KILLCAM");

if(!isdefined(self.kc_skiptext))
{
self.kc_skiptext = newClientHudElem(self);
self.kc_skiptext.archived = false;
self.kc_skiptext.x = 0;
self.kc_skiptext.alignX = "center";
self.kc_skiptext.alignY = "middle";
self.kc_skiptext.horzAlign = "center_safearea";
self.kc_skiptext.vertAlign = "top";
self.kc_skiptext.sort = 1; // force to draw after the bars
self.kc_skiptext.font = "default";

if(level.splitscreen)
{
self.kc_skiptext.y = 52;
self.kc_skiptext.fontscale = 1.6;
}
else
{
self.kc_skiptext.y = 70;
self.kc_skiptext.fontscale = 2;
}
}
if(isdefined(respawn))
self.kc_skiptext setText(&"PLATFORM_PRESS_TO_RESPAWN");
else
self.kc_skiptext setText(&"PLATFORM_PRESS_TO_SKIP");

if(!level.splitscreen)
{
if(!isdefined(self.kc_timer))
{
self.kc_timer = newClientHudElem(self);
self.kc_timer.archived = false;
self.kc_timer.x = 0;
self.kc_timer.y = -32;
self.kc_timer.alignX = "center";
self.kc_timer.alignY = "middle";
self.kc_timer.horzAlign = "center_safearea";
self.kc_timer.vertAlign = "bottom";
self.kc_timer.fontScale = 3.5;
self.kc_timer.sort = 1;
}

self.kc_timer setTenthsTimer(self.archivetime - delay);
}

self thread spawnedKillcamCleanup();
self thread waitSkipKillcamButton();
self thread waitKillcamTime();
self waittill("end_killcam");
//izno: added the following 2 lines to clean up the freezecontrols/disableweapon caused by the nadekillcam
self freezecontrols(false);
self enableweapon();
self removeKillcamElements();

self.sessionstate = "dead";
self.spectatorclient = -1;
self.archivetime = 0;
self.psoffsettime = 0;

self.killcam = undefined;

self thread maps\mp\gametypes\_spectating::setSpectatePermissi ons();
}
//izno: added the following function for nade-killcam purposes
donadefollow(nade)
{
self endon("disconnect");
self endon("end_killcam");
counter = gettime() - self.archivetime * 1000;
while(counter < nade.create_time)
{
counter += 50;
wait 0.05;
}
self freezecontrols(true);
self disableweapon();
frames_back = int((gettime() - nade.create_time) / 50);
userorgs = [];
user_alive = [];
for(i = 0; i < nade.prev_org.size; i++)
{
if(self.prev_org.size - frames_back + i < 0)
{
userorgs[i] = (0, 0, 0);
user_alive[i] = false;
}
else
{
userorgs[i] = self.prev_org[self.prev_org.size - frames_back + i];
user_alive[i] = self.was_alive[self.was_alive.size - frames_back + i];
}
}
self allowSpectateTeam("allies", false);
self allowSpectateTeam("axis", false);
self allowSpectateTeam("freelook", true);
self allowSpectateTeam("none", true);
a = spawn("script_model", nade.prev_org[0]);
b = spawn("script_model", userorgs[0]);
a setmodel("xmodel/weapon_potato");
b setmodel("xmodel/prop_barrel_benzin");
a hide();
b hide();
a showtoplayer(self);
if(user_alive[0])
b showtoplayer(self);
a thread deleteonevent("disconnect", self);
b thread deleteonevent("disconnect", self);
a thread deleteonevent("end_killcam", self);
b thread deleteonevent("end_killcam", self);
for(i = 0; i < nade.prev_org.size; i++)
{
if(user_alive[i])
b showtoplayer(self);
else
b hide();
self setplayerangles((90, 0, 0));
//uncomment the next 2 lines to actually follow the grenade instead of looking at it from above - it's very laggy though
//self setplayerangles(vectortoangles(userorgs[i] - (nade.prev_org[i]+ (0, 0, 50))));
//self setorigin(nade.prev_org[i] + (0, 0, 50) - maps\mp\_utility::vectorscale(vectornormalize(make 2d(userorgs[i] - nade.prev_org[i])), 50));
self setorigin(nade.prev_org[i] + (0, 0, 150));
a.origin = nade.prev_org[i];
b.origin = userorgs[i];
if(i < nade.prev_org.size - 1)
{
a moveto(nade.prev_org[i + 1], 0.05);
b moveto(userorgs[i + 1], 0.05);
}
wait 0.05;
}
a notify("done");
b notify("done");
a delete();
b delete();
}
//izno: helper function
make2d(vec)
{
return (vec[0], vec[1], 0);
}
//izno: helper function
deleteonevent(ev, us)
{
if(ev == "disconnect")
us endon("end_killcam");
else
us endon("disconnect");
self endon("done");
us waittill(ev);
if(isdefined(self))
self delete();
}

waitKillcamTime()
{
self endon("disconnect");
self endon("end_killcam");

wait(self.archivetime - 0.05);
self notify("end_killcam");
}

waitSkipKillcamButton()
{
self endon("disconnect");
self endon("end_killcam");

while(self useButtonPressed())
wait .05;

while(!(self useButtonPressed()))
wait .05;

self notify("end_killcam");
}

removeKillcamElements()
{
if(isDefined(self.kc_topbar))
self.kc_topbar destroy();
if(isDefined(self.kc_bottombar))
self.kc_bottombar destroy();
if(isDefined(self.kc_title))
self.kc_title destroy();
if(isDefined(self.kc_skiptext))
self.kc_skiptext destroy();
if(isDefined(self.kc_timer))
self.kc_timer destroy();
}

spawnedKillcamCleanup()
{
self endon("end_killcam");

self waittill("spawned");
self removeKillcamElements();
}
(all changes are highlighted with //izno before/after them

Create maps\mp\gametypes\_nadekillcam.gsc with this in it:


init()
{
thread waitforconnect();
}

findnade(type)
{
nades = getentarray("grenade", "classname");
for(i = 0; i < nades.size; i++)
{
if(!isdefined(nades[i].monitoring) && distancesquared(self.origin, nades[i].origin) < 100 * 100)
{
nades[i].monitoring = true;
nades[i] thread domonitor(self, type);
}
}
}

waitforconnect()
{
while(true)
{
level waittill("connecting", player);
player thread waitforspawn();
}
}

waitforspawn()
{
self endon("disconnect");
self thread storeorigins();
while(true)
{
self waittill("spawned_player");
self thread monitorplayer();
}
}

storeorigins()
{
self endon("disconnect");
self.prev_org = [];
self.was_alive = [];
while(true)
{
if(self.prev_org.size > 200)
{
for(i = 1; i < self.prev_org.size; i++)
self.prev_org[i - 1] = self.prev_org[i];
self.prev_org[self.prev_org.size - 1] = self.origin;
}
else
self.prev_org[self.prev_org.size] = self.origin;
if(self.was_alive.size > 200)
{
for(i = 1; i < self.was_alive.size; i++)
self.was_alive[i - 1] = self.was_alive[i];
self.was_alive[self.was_alive.size - 1] = (isdefined(self.sessionstate) && self.sessionstate == "playing");
}
else
self.was_alive[self.was_alive.size] = (isdefined(self.sessionstate) && self.sessionstate == "playing");
wait 0.05;
}
}

monitorplayer()
{
self endon("disconnect");
self endon("spawned_player");
old_nadecount = 0;
old_smokecount = 0;
while(isdefined(self.sessionstate) && self.sessionstate == "playing")
{
nadecount = self getammocount("frag_grenade_american_mp") + self getammocount("frag_grenade_russian_mp") + self getammocount("frag_grenade_british_mp") + self getammocount("frag_grenade_german_mp");
smokecount = self getammocount("smoke_grenade_american_mp") + self getammocount("smoke_grenade_russian_mp") + self getammocount("smoke_grenade_british_mp") + self getammocount("smoke_grenade_german_mp");
if(!isdefined(self.sessionstate) || self.sessionstate != "playing")
return;
if(nadecount < old_nadecount)
self findnade("frag");
else if(smokecount < old_smokecount)
self findnade("smoke");
wait 0.05;
old_nadecount = nadecount;
old_smokecount = smokecount;
}
}

cleanup_array(arr)
{
if(!isdefined(arr))
return [];
new = [];
for(i = 0; i < arr.size; i++)
{
if(isdefined(arr[i]))
new[new.size] = arr[i];
}
return new;
}

domonitor(owner, type)
{
clone = spawn("script_origin", (0,0,0));
clone.prev_org = [];
clone.prev_org[clone.prev_org.size] = self.origin;
clone.create_time = gettime();
clone.exploded = undefined;
clone.type = type;
owner.nades = cleanup_array(owner.nades);
owner.nades[owner.nades.size] = clone;

t = 0;
while(t < 5 && isdefined(self))
{
clone.prev_org[clone.prev_org.size] = self.origin;
t += 0.05;
wait 0.05;
}
if(isdefined(self))
{
//was a smoke grenade...
clone.exploded = true;
wait 30;
if(isdefined(self))
{
self delete(); //clean up activision mess that didnt delete smokegrenades and would allow an entity overflow
clone delete();
}
}
else
{
clone.exploded = true;
clone deleteaftertime(20);
}
}

deleteaftertime(t)
{
wait t;
if(isdefined(self))
self delete();
}

and finally, replace this code in your gametype.gsc:


delay = 2; // Delay the player becoming a spectator till after he's done dying
wait delay; // ?? Also required for Callback_PlayerKilled to complete before respawn/killcam can execute
if(doKillcam && level.killcam)
self maps\mp\gametypes\_killcam::killcam(attackerNum, delay, psOffsetTime, true);

self thread respawn();

with this:


//izno: the next few lines of code (until delay = 2) is added to find if the player was killed by a nade and, if so, which one
grenade = undefined;
if(isdefined(sWeapon) && (sWeapon == "frag_grenade_german_mp" || sWeapon == "frag_grenade_american_mp" || sWeapon == "frag_grenade_british_mp" || sWeapon == "frag_grenade_russian_mp"))
{
if(isdefined(attacker) && isdefined(attacker.nades))
{
for(i = 0; i < attacker.nades.size; i++)
{
if(!isdefined(attacker.nades[i]))
continue;
if(!isdefined(attacker.nades[i].exploded) && attacker.nades[i].type == "frag")
{
grenade = attacker.nades[i];
break;
}
}
}
}
delay = 2; // Delay the player becoming a spectator till after he's done dying
wait delay; // ?? Also required for Callback_PlayerKilled to complete before respawn/killcam can execute
if(doKillcam && level.killcam)
self maps\mp\gametypes\_killcam::killcam(attackerNum, delay, psOffsetTime, true, grenade); //izno: added grenade as input for the killcam function

self thread respawn();


Thats all.

Buglist:
- In free spec mode (used to track the nade) during killcam, all players are invisible, hence the barrel model instead of the playermodel
- In free spec mode during killcam, all items are invisible, hence the potato model instead of the grenade model
- In free spec mode during killcam, no fx is being played (and the nade-explosion hole is already in place by then), thus, no big kaboom.

These are all bugs due to engine limitations. Dont expect miracles from the engine of a 9 year old game (oktober 2005)

xulikav
19th July 2016, 15:37
i try this code in my sd mod but didnt work can somone help me ?grenade = undefined;
if(isdefined(sWeapon) && (sWeapon == "frag_grenade_german_mp" || sWeapon == "frag_grenade_american_mp" || sWeapon == "frag_grenade_british_mp" || sWeapon == "frag_grenade_russian_mp"))
{
if(isdefined(attacker) && isdefined(attacker.nades))
{
for(i = 0; i < attacker.nades.size; i++)
{
if(!isdefined(attacker.nades[i]))
continue;
if(!isdefined(attacker.nades[i].exploded) && attacker.nades[i].type == "frag")
{
grenade = attacker.nades[i];
break;
}
}
}
}


delay=4;
wait 4;

if(level.roundended)
{
players = getentarray("player", "classname");
for(i = 0; i < players.size; i++)
{
player = players[i];

if(player.pers["team"]!="spectator")
player thread maps\mp\gametypes\_killcam::killcam(attackerNum, delay, psOffsetTime, true, grenade);
}
}

Paho
19th July 2016, 16:36
it's working but gone through texture. Func setarchive() changed player model to barel model.

IzNoGoD
19th July 2016, 16:45
it's working but gone through texture. Func setarchive() changed player model to barel model.



Buglist:
- In free spec mode (used to track the nade) during killcam, all players are invisible, hence the barrel model instead of the playermodel
- In free spec mode during killcam, all items are invisible, hence the potato model instead of the grenade model
- In free spec mode during killcam, no fx is being played (and the nade-explosion hole is already in place by then), thus, no big kaboom.

These are all bugs due to engine limitations. Dont expect miracles from the engine of a 9 year old game (oktober 2005)

Can you even read?

xulikav
19th July 2016, 18:17
izo bizo the nade killcam its not working its normal killcam why men how to fix it?
and its hard bro

xulikav
19th July 2016, 19:24
i never read a script for you and it worked before when i try it.
can you explain how to make it work after onjecting all these codes because i see normal killcam after doing it

IzNoGoD
19th July 2016, 22:31
i never read a script for you and it worked before when i try it.
can you explain how to make it work after onjecting all these codes because i see normal killcam after doing it

This is code i wrote almost 2 years ago. I have no knowledge about it anymore whatsoever aside from whats in the OP.

xulikav
19th July 2016, 23:12
add me on steam pichatchoo

i no more see you on skype

IzNoGoD
20th July 2016, 06:49
I removed you on both because of your constant "help me with this then I will never ask anything else of you again" promises.

xulikav
20th July 2016, 12:56
hey izo bizo when i did the nade killcam the nade go to player but the players always dead
here a video the players are alive how to make the players when they get killed with nade are archived

https://www.youtube.com/watch?v=KIYhE42FN9g

xulikav
20th July 2016, 13:26
this is my nade how its looks like


https://www.youtube.com/watch?v=jWflFSuyINU


the other dude nade looks like



https://www.youtube.com/watch?v=KIYhE42FN9g

maxdamage99
20th July 2016, 13:45
xulikav stupid, no help him :D he abuse bots for gametracker.com ranks, report!!!

xulikav
20th July 2016, 14:09
xulikav stupid, no help him :D he abuse bots for gametracker.com ranks, report!!!


you are fucking abuser you abuse people for money i deleted you from Skype you fucking asshole

IzNoGoD
20th July 2016, 15:37
How was I unclear in my previous posts?

This doesnt help.

https://i.gyazo.com/3514f9c5dad563b54732ba03802b7898.png

xulikav
20th July 2016, 17:48
if you dont wanan help say and dont start fucking with me bye this stupid forums full with abusers and assholes and selfish motherfuckers

suck000
22nd July 2016, 22:17
I'm trying to make this with zpam 207. I did what's exactly typed. But i can't get it working. Any suggestions ?