Results 1 to 10 of 16

Thread: [Killcam] Nade Killcam

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts

    [Killcam] Nade Killcam

    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:
    PHP Code:
    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"killcamtrue);
        
    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(attackerNumdelayoffsetTimerespawnnade//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.0;
            
    self.kc_topbar.0;
            
    self.kc_topbar.horzAlign "fullscreen";
            
    self.kc_topbar.vertAlign "fullscreen";
            
    self.kc_topbar.alpha 0.5;
            
    self.kc_topbar setShader("black"640112);
        }

        if(!
    level.splitscreen && !isdefined(self.kc_bottombar))
        {
            
    self.kc_bottombar newClientHudElem(self);
            
    self.kc_bottombar.archived false;
            
    self.kc_bottombar.0;
            
    self.kc_bottombar.368;
            
    self.kc_bottombar.horzAlign "fullscreen";
            
    self.kc_bottombar.vertAlign "fullscreen";
            
    self.kc_bottombar.alpha 0.5;
            
    self.kc_bottombar setShader("black"640112);
        }

        if(!
    isdefined(self.kc_title))
        {
            
    self.kc_title newClientHudElem(self);
            
    self.kc_title.archived false;
            
    self.kc_title.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.22;
            else
                
    self.kc_title.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.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.52;
                
    self.kc_skiptext.fontscale 1.6;
            }
            else
            {
                
    self.kc_skiptext.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.0;
                
    self.kc_timer.= -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::setSpectatePermissions();
    }
    //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(
    0nade.prev_org.sizei++)
        {
            if(
    self.prev_org.size frames_back 0)
            {
                
    userorgs[i] = (000);
                
    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);
        
    spawn("script_model"nade.prev_org[0]);
        
    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(
    0nade.prev_org.sizei++)
        {
            if(
    user_alive[i])
                
    b showtoplayer(self);
            else
                
    b hide();
            
    self setplayerangles((9000));
            
    //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(make2d(userorgs[i] - nade.prev_org[i])), 50));
            
    self setorigin(nade.prev_org[i] + (00150));
            
    a.origin nade.prev_org[i];
            
    b.origin userorgs[i];
            if(
    nade.prev_org.size 1)
            {
                
    a moveto(nade.prev_org[1], 0.05);
                
    b moveto(userorgs[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(evus)
    {
        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:
    PHP Code:
    init()
    {
        
    thread waitforconnect();
    }

    findnade(type)
    {
        
    nades getentarray("grenade""classname");
        for(
    0nades.sizei++)
        {
            if(!
    isdefined(nades[i].monitoring) && distancesquared(self.originnades[i].origin) < 100 100)
            {
                
    nades[i].monitoring true;
                
    nades[ithread domonitor(selftype);
            }
        }
    }

    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(
    1self.prev_org.sizei++)
                    
    self.prev_org[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(
    1self.was_alive.sizei++)
                    
    self.was_alive[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(
    0arr.sizei++)
        {
            if(
    isdefined(arr[i]))
                new[new.
    size] = arr[i];
        }
        return new;
    }

    domonitor(ownertype)
    {
        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;

        
    0;
        while(
    && isdefined(self))
        {
            clone.
    prev_org[clone.prev_org.size] = self.origin;
            
    += 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:
    Code:
    	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:
    PHP Code:
        //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(
    0attacker.nades.sizei++)
                {
                    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(attackerNumdelaypsOffsetTimetruegrenade); //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)
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  2. The Following 6 Users Say Thank You to IzNoGoD For This Useful Post:

    Kemi (30th November 2015),kung foo man (5th December 2014),m4ki (13th February 2015),Ni3ls (5th December 2014),voron00 (29th March 2016),ysniper (27th April 2016)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •