Release BO2 Killcam Mod

Cxwh

Veteran
Messages
64
Reaction score
45
Points
793
Haven't seen this yet and decided to spent a few hours on making this (took me longer than it should have). This let's you rewatch your last kill and lets it look like the final killcam - the game obviously doesn't have to end for this.

A video so people know what I'm talking about

Anyway so here's the source:
Code:
#include maps\mp\_utility;
#include common_scripts\utility;
#include maps\mp\gametypes\_hud_util;
#include maps\mp\gametypes\_hud_message;

//need to include these in order for it to work
#include maps\mp\gametypes\_killcam;
#include maps\mp\gametypes\_globallogic;
#include maps\mp\gametypes\_globallogic_spawn;

/*
    Made using SeriousHD's GSX Studio
*/

init() {
    //copy callback
    level.alt = level.onplayerkilled;
    level.onplayerkilled = ::onKilled;

    level.debug = 1;
    level thread onPlayerConnect();
}

onPlayerConnect() {
    for(;;) {
        level waittill("connected", player);
        player thread onPlayerSpawned();
    }
}

onPlayerSpawned() {
    self endon("disconnect");

    self thread monitor();
    for(;;) {
        self waittill("spawned_player");
   
        //don't want bots to have ghost perk
        if(self.pers["isBot"])
            self clearperks();
        self freezecontrols(self.pers["isBot"]);
   
        //uav
        self setclientuivisibilityflag("g_compassShowEnemies", 1);
    }
}

monitor() {
    self endon("disconnect");
    level endon("game_ended");

    for(timer = 7; true; timer -= 0.05) {
        if(self ActionSlotTwoButtonPressed())
            self watchLastKill();

        if(self ActionSlotOneButtonPressed()) {
            if(level.debug && self isHost())
                exitLevel();
        }
   
        //print controls
        if(timer < 0) {
            self iprintln("Exit Level - [{+actionslot 1}]");
            self iprintln("Watch Last Kill - [{+actionslot 2}]");
            timer = 14;
        }
        wait 0.05;
    }
}

onKilled(einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration) {
    //doesn't change gamemode specific callbacks - so you can still score in tdm etc.
    thread [[ level.alt ]](einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration);

    //ignore if kill was suicide
    if(self == attacker)
        return;

    //info
    attacker iprintln("Killed ^1" + self.name);
    self iprintln("Killed by ^1" + attacker.name);

    sweapon = updateweapon(einflictor, sweapon);
    lpattacknum = attacker getentitynumber();
    deathtimeoffset = 0;

    killcamentity = self maps\mp\gametypes\_globallogic_player::getkillcamentity(attacker, einflictor, sweapon);
    if(isDefined(killcamentity)) {
        killcamentityindex = killcamentity getentitynumber();
        if(isDefined(killcamentity.starttime))
            killcamentitystarttime = killcamentity.starttime;
        else
            killcamentitystarttime = killcamentity.birthtime;
   
        if(!isDefined(killcamentitystarttime))
            killcamentitystarttime = 0;
    }

    perks = [];
    killstreaks = maps/mp/gametypes/_globallogic::getkillstreaks(attacker);

    level.lastAttacker = attacker;
    level thread maps/mp/gametypes/_killcam::recordkillcamsettings(lpattacknum, self getentitynumber(), sweapon, self.deathtime, deathtimeoffset, psoffsettime, killcamentityindex, killcamentitystarttime, perks, killstreaks, attacker);
}

finalkillcam(winner) {
    self endon("disconnect");
    level endon("game_ended");

    setmatchflag("final_killcam", 0);
    setmatchflag("round_end_killcam", 1);

    if(level.console)
        self maps/mp/gametypes/_globallogic_spawn::setthirdperson(0);

    killcamsettings = level.finalkillcamsettings[winner];
    postdeathdelay = (getTime() - killcamsettings.deathtime)/1000;
    predelay = postdeathdelay + killcamsettings.deathtimeoffset;
    camtime = maps/mp/gametypes/_killcam::calckillcamtime(killcamsettings.weapon, killcamsettings.entitystarttime, predelay, 0, undefined);
    postdelay = maps/mp/gametypes/_killcam::calcpostdelay();

    killcamoffset = camtime + predelay;
    killcamlength = (camtime + postdelay) - 0.05;
    killcamstarttime = getTime() - (killcamoffset * 1000);

    self notify("begin_killcam");
    self.sessionstate = "spectator";
    self.spectatorclient = killcamsettings.spectatorclient;
    self.killcamentity = -1;

    if(killcamsettings.entityindex >= 0)
        self thread maps/mp/gametypes/_killcam::setkillcamentity(killcamsettings.entityindex, killcamsettings.entitystarttime - killcamstarttime - 100);

    self.killcamtargetentity = killcamsettings.targetentityindex;
    self.archivetime = killcamoffset;
    self.killcamlength = killcamlength;
    self.psoffsettime = killcamsettings.offsettime;

    team = getFirstArrayKey(level.teams);
    while(isDefined(team)) {
        _team = level.teams[team];
        self allowspectateteam(_team, 1);
        team = getNextArrayKey(level.teams, team);
    }

    self allowspectateteam("freelook", 1);
    self allowspectateteam("none", 1);
    self thread maps/mp/gametypes/_killcam::endedfinalkillcamcleanup();
    wait 0.05;

    if(self.archivetime <= predelay) {
        self.sessionstate = "dead";
        self.spectatorclient = -1;
        self.killcamentity = -1;
        self.archivetime = 0;
        self.psoffsettime = 0;
        self notify("end_killcam");
        return;
    }

    self thread maps/mp/gametypes/_killcam::checkforabruptkillcamend();
    self.killcam = 1;

    //add kc timer if isn'splitscreen
    if(!self issplitscreen())
        self maps/mp/gametypes/_killcam::addkillcamtimer(camtime);

    self thread maps/mp/gametypes/_killcam::waitkillcamtime();
    self thread maps/mp/gametypes/_killcam::waitfinalkillcamslowdown(level.finalkillcamsettings[winner].deathtime, killcamstarttime);

    self waittill("end_killcam");
    self maps/mp/gametypes/_killcam::endkillcam(1);

    //reset flags
    setmatchflag("final_killcam", 0);
    setmatchflag("round_end_killcam", 0);

    //respawn
    self [[ level.spawnplayer ]]();
    self.sessionstate = "playing";

    //reset timescale
    setSlowMotion(1, 1, 0);
    setDvar("Timescale", 1);
}

updateweapon(einflictor, sweapon) {
    if(sweapon == "none" && isDefined(einflictor)) {
        if(isDefined(einflictor.targetname) && einflictor.targetname == "explodable_barrel")
            sweapon = "explodable_barrel_mp";
        else {
            if(isDefined(einflictor.destructible_type) && issubstr(einflictor.destructible_type, "vehicle_"))
                sweapon = "destructible_car_mp";
        }
    }
    return sweapon;
}

watchLastKill() {
    if(!isDefined(level.lastAttacker))
        return;

    //save pos and angles
    origin = self.origin;
    angles = self.angles;

    wait 0.1;
    self finalkillcam(level.lastAttacker.team);
    wait 0.1;

    //respawn
    self freezecontrols(false);
    self setOrigin(origin);
    self setPlayerAngles(angles);
}

/* Incase
    //normal killcam instead of final killcam
    attacker maps/mp/gametypes/_killcam::killcam(lpattacknum, self getentitynumber(), killcamentity, killcamentityindex, killcamentitystarttime, sweapon, self.deathtime, deathtimeoffset, psoffsettime, false, undefined, perks, killstreaks, attacker);
*/
 
Last edited:
Top