rendered paste body// GPL License - see http://opensource.org/licenses/gpl-license.php
// Copyright 2006 *nixCoders team - don't forget to credit us
#include <unistd.h>
#include "eth.h"
/*
==============================
Some utils functions
==============================
*/
int getSpawntimer(qboolean enemySpawn) {
int team = eth.clientInfo[eth.cg_snap->ps.clientNum].team;
int limbotime = 0;
// Reverse the value from clientinfo[myself].team to make the function return the spawn time of the other team
if(enemySpawn == qtrue) {
if (team == TEAM_AXIS) {
team = TEAM_ALLIES;
limbotime = eth.cg_bluelimbotime;
} else if (team == TEAM_ALLIES) {
team = TEAM_AXIS;
limbotime = eth.cg_redlimbotime;
} else
return -1;
} else {
if (team == TEAM_AXIS) {
limbotime = eth.cg_redlimbotime;
} else if (team == TEAM_ALLIES) {
limbotime = eth.cg_bluelimbotime;
} else
return -1;
}
// Sanity check
if (limbotime == 0) {
ethLog("warning: can't get spawntimer for team %i", team);
return -1;
}
return (int)(1 + (limbotime - ((eth.cgs_aReinfOffset[team] + eth.cg_time - eth.cgs_levelStartTime) % limbotime)) * 0.001f);
}
int findSatchel() {
int entityNum = 0;
for (; entityNum < MAX_GENTITIES; entityNum++) {
if ((eth.cg_entities[entityNum].currentState->weapon == WP_SATCHEL)
&& (eth.cg_entities[entityNum].currentState->clientNum == eth.cg_snap->ps.clientNum)
&& (!VectorCompare(eth.entities[entityNum].origin, vec3_origin)))
return entityNum;
}
#ifdef ETH_DEBUG
ethDebug("satchel cam: don't find satchel for %i", eth.cg_snap->ps.clientNum);
#endif
return -1;
}
qboolean isKeyActionDown(char *action) {
int key1, key2;
orig_syscall(CG_KEY_BINDINGTOKEYS, action, &key1, &key2);
if (syscall_CG_Key_IsDown(key1) || syscall_CG_Key_IsDown(key2))
return qtrue;
else
return qfalse;
}
int getIdByName (const char *name, int len) {
int i;
if (!len)
len = strlen(name);
for (i=0; i < MAX_CLIENTS; i++)
if (eth.clientInfo[i].infoValid && !strncmp(eth.clientInfo[i].name, name, len))
return i;
return -1;
}
qboolean isVisible(vec3_t target) {
trace_t trace;
eth.CG_Trace(&trace, eth.cg_refdef.vieworg, NULL, NULL, target, eth.cg_snap->ps.clientNum, CONTENTS_SOLID | CONTENTS_CORPSE);
return (trace.fraction == 1.0f);
}
qboolean isPlayerVisible(vec3_t target, int player) {
trace_t traceVisible;
eth.CG_Trace(&traceVisible, eth.cg_refdef.vieworg, NULL, NULL, target, eth.cg_snap->ps.clientNum, CONTENTS_SOLID | CONTENTS_CORPSE);
trace_t tracePlayer;
eth.CG_Trace(&tracePlayer, eth.cg_refdef.vieworg, NULL, NULL, target, eth.cg_snap->ps.clientNum, CONTENTS_SOLID | CONTENTS_BODY);
//printf("XXX: want %i got %i\n", player, tracePlayer.entityNum);
return ((traceVisible.fraction == 1.0f) && (tracePlayer.entityNum == player));
}
void ethLog(const char *format, ...) {
printf("eth: ");
va_list arglist;
va_start(arglist, format);
vprintf(format, arglist);
va_end(arglist);
printf("\n");
#ifdef ETH_DEBUG
// If log file
if (debugFile) {
fprintf(debugFile, "log: ");
va_list arglist;
va_start(arglist, format);
vfprintf(debugFile, format, arglist);
va_end(arglist);
fprintf(debugFile, "\n");
}
#endif
}
#ifdef ETH_DEBUG
FILE *debugFile = NULL;
void ethDebug(const char *format, ...) {
// If log file
if (debugFile) {
va_list arglist;
va_start(arglist, format);
vfprintf(debugFile, format, arglist);
va_end(arglist);
fprintf(debugFile, "\n");
}
}
#endif // ETH_DEBUG
void fatalError(const char *msg) {
char str[256];
snprintf(str, sizeof(str), "A fatal error has occured. You must restart the game.\n\nError: %s\n\n\n*nixCoders eth-v%s", msg, ETH_VERSION);
orig_syscall(CG_ERROR, str);
#ifdef ETH_DEBUG
ethLog("fatal error: %s", msg);
#endif
}
// Helper function for get ouput of a system command
// This function return the first line of this command output
char *getOutputSystemCommand(const char *command) {
static char buf[256];
memset(buf, 0, sizeof(buf));
FILE *cmd = popen(command, "r");
int c;
int count = 0;
while (((c = getc(cmd)) != EOF) && (count < (sizeof(buf) - 1))) {
if (c == '\n')
break;
buf[count++] = c;
}
pclose(cmd);
return buf;
}
// If cgame is load, send a UI_PRINT message else just show a message at console,
// WARNING ! use this function only when call from ui vmMain. ex: irc and game command
#define MESSAGE_COLOR "^n"
void gameMessage(qboolean forceConsole, char *format, ...) {
char msg[MAX_SAY_TEXT];
memset(msg, 0, sizeof(msg));
char buffer[sizeof(msg)];
memset(buffer, 0, sizeof(buffer));
va_list arglist;
va_start(arglist, format);
vsnprintf(msg, sizeof msg, format, arglist);
va_end(arglist);
if (eth.hookLoad && !forceConsole) {
snprintf(buffer, sizeof(buffer), "echo \"" MESSAGE_COLOR "%s\"\n", msg);
orig_syscall(UI_CMD_EXECUTETEXT, EXEC_APPEND, buffer);
} else {
snprintf(buffer, sizeof(buffer), MESSAGE_COLOR "%s\n", msg);
orig_syscall(UI_PRINT, buffer);
}
}
void doAutoVote(char *str) {
char *ptr = strstr(str, "^7 called a vote. Voting for: ");
int id = getIdByName(str, ptr - str);
// id not found
if (id == -1)
return;
// who votes
switch (eth.clientInfo[id].targetType) {
case PLIST_FRIEND:
syscall_CG_SendConsoleCommand("vote yes\n");
return;
case PLIST_TEAMKILLER:
syscall_CG_SendConsoleCommand("vote no\n");
return;
default:
break;
}
// Voter is not a friend/teamkiller
ptr += strlen("^7 called a vote. Voting for: ");
if (!strncmp(ptr, "KICK ", 5) || !strncmp(ptr, "MUTE ", 5)) {
ptr += 5;
id = getIdByName(ptr, strrchr(ptr, '\n') - ptr);
// id not found
if (id == -1)
return;
// vote against client
if (id == eth.cg_clientNum) {
syscall_CG_SendConsoleCommand("vote no\n");
return;
}
// who is voted against
switch (eth.clientInfo[id].targetType) {
case PLIST_FRIEND:
syscall_CG_SendConsoleCommand("vote no\n");
return;
case PLIST_TEAMKILLER:
syscall_CG_SendConsoleCommand("vote yes\n");
return;
default:
break;
}
}
}
// Auto request medic
#define TIME_BETWEEN_REQUEST 5000
void autoRequestMedic() {
if (eth.cg_snap->ps.clientNum != eth.cg_clientNum)
return;
static int lastRequestTime = 0;
if (lastRequestTime + TIME_BETWEEN_REQUEST > eth.cg_time)
return;
// If need revive
if (eth.cg_entities[eth.cg_clientNum].currentState->eFlags & EF_DEAD) {
int vsay = (int)(2.0f * (rand() / (RAND_MAX + 1.0f)));
if (!vsay)
syscall_CG_SendConsoleCommand("vsay_team Medic\n");
else
syscall_CG_SendConsoleCommand("vsay FTReviveMe\n");
lastRequestTime = eth.cg_time;
// If need health
} else if (eth.cg_snap->ps.stats[STAT_HEALTH] < 40) {
int vsay = (int)(2.0f * (rand() / (RAND_MAX + 1.0f)));
if (!vsay)
syscall_CG_SendConsoleCommand("vsay_team Medic\n");
else
syscall_CG_SendConsoleCommand("vsay FTHealMe\n");
lastRequestTime = eth.cg_time;
}
}
// Calc muzzle
// kobj fixed the muzzle thing :D (Hooked server bullet_fire, and they match)
void setCurrentMuzzle() {
VectorCopy(eth.cg_refdef.vieworg, eth.muzzle);
if(eth.cg_snap->ps.viewangles[PITCH] > 30 && (eth.cg_snap->ps.eFlags & EF_CROUCHING))
eth.muzzle[2] += 30.0 - eth.cg_snap->ps.viewheight;
SnapVector( eth.muzzle );
}
qboolean isAimbotWeapon(int weapon){
switch( weapon ){
case WP_AMMO:
case WP_ARTY:
case WP_MEDIC_SYRINGE:
case WP_DYNAMITE:
case WP_SMOKETRAIL:
case WP_MAPMORTAR:
case WP_MEDKIT:
case WP_BINOCULARS:
case WP_PLIERS:
case WP_LANDMINE:
case WP_SATCHEL:
case WP_TRIPMINE:
case WP_SMOKE_BOMB:
case WP_MORTAR:
case WP_MEDIC_ADRENALINE:
return qfalse;
default:
return qtrue;
}
}
//Speedshooting for single shot weapons :D
qboolean isSingleShootWeapon(){
int weapon = eth.cg_entities[eth.cg_clientNum].currentState->weapon;
switch( weapon ){
case WP_K43:
case WP_GARAND:
case WP_CARBINE:
case WP_KAR98:
case WP_LUGER:
case WP_SILENCER:
case WP_AKIMBO_LUGER:
case WP_AKIMBO_SILENCEDLUGER:
case WP_COLT:
case WP_SILENCED_COLT:
case WP_AKIMBO_COLT:
case WP_AKIMBO_SILENCEDCOLT:
return qtrue;
default:
return qfalse;
}
}
/*
==============================
Config stuff
==============================
*/
char *getConfigFilename() {
// If config filename is set by enviromment var
if (getenv("ETH_CONF_FILE"))
return getenv("ETH_CONF_FILE");
static char filename[PATH_MAX];
snprintf(filename, sizeof(filename), "%s/%s", getenv("HOME"), ETH_CONFIG_FILE);
return filename;
}
void readConfig() {
FILE *file;
// Init all user vars with the default value
int count = 0;
for (; count < VARS_TOTAL; count++)
seth.value[count] = seth.vars[count].defaultValue;
if ((file = fopen(getConfigFilename(), "rb")) == NULL)
return;
// Get config file line by line
char line[1024];
while (fgets(line, sizeof(line) - 1, file) != 0) {
char *sep = strrchr(line, '=');
*sep = '\0'; // Separate name from value
if( !sep )
fatalError("Config error. Check your config file!");
// Search this var
int count = 0;
if( !strcmp(line,"ksFormat") ){
strncpy(dieFormat, Q_ValidStr(sep+1), sizeof(ksFormat));
} else if( !strcmp(line,"dieFormat") ) {
strncpy(dieFormat, Q_ValidStr(sep+1), sizeof(ksFormat));
} else if( !strcmp(line,"bnFormat") ) {
strncpy(bnFormat, Q_ValidStr(sep+1), sizeof(ksFormat));
} else if( !strcmp(line,"skFormat") ) {
strncpy(skFormat, Q_ValidStr(sep+1), sizeof(ksFormat));
} else {
for (; count < VARS_TOTAL; count++) {
if (!seth.vars[count].cvarName) {
ethLog("readConfig: error: VAR_%i undefine", count);
} else if (!strcmp(line, seth.vars[count].cvarName)) {
seth.value[count] = atof(sep + 1);
break;
} else if ((count + 1) == VARS_TOTAL) {
ethLog("readConfig: don't know this var: [%s]", line);
}
if (count == VAR_CHUD)
if (atoi(sep + 1))
syscall_CG_SendConsoleCommand(va("cg_draw2d %s\n", seth.value[count] ? "0" : "1"));
}
}
}
fclose(file);
}
void writeConfig() {
FILE *file;
if ((file = fopen(getConfigFilename(), "w")) == NULL) {
ethLog("eth: can't write config file.");
return;
}
int count = 0;
fprintf(file,"ksFormat=%s\n",ksFormat);
fprintf(file,"bnFormat=%s\n",bnFormat);
fprintf(file,"dieFormat=%s\n",dieFormat);
fprintf(file,"skFormat=%s\n",skFormat);
for (; count < VARS_TOTAL; count++) {
if (!seth.vars[count].cvarName)
ethLog("writeConfig: error: VAR_%i undefine", count);
else if (seth.value[count] == (float)(int)seth.value[count])
fprintf(file, "%s=%i\n", seth.vars[count].cvarName, (int)seth.value[count]);
else
fprintf(file, "%s=%.2f\n", seth.vars[count].cvarName, seth.value[count]);
}
fclose(file);
}
/*
==============================
Console actions
==============================
*/
void initActions() {
eth.actions[ACTION_ATTACK] = (ethAction_t){ 0, 0, "+attack\n", "-attack\n" };
eth.actions[ACTION_BACKWARD] = (ethAction_t){ 0, 0, "+backward\n", "-backward\n" };
eth.actions[ACTION_BINDMOUSE1] = (ethAction_t){ 1, 1, "bind mouse1 +attack\n", "unbind mouse1\n" };
eth.actions[ACTION_CROUCH] = (ethAction_t){ 0, 0, "+movedown\n", "-movedown\n" };
eth.actions[ACTION_JUMP] = (ethAction_t){ 0, 0, "+moveup\n", "-moveup\n" };
eth.actions[ACTION_PRONE] = (ethAction_t){ 0, 0, "+prone; -prone\n", "+moveup; -moveup\n" };
eth.actions[ACTION_RUN] = (ethAction_t){ 0, 0, "+sprint; +movedown; +forward\n", "-sprint; -forward\n" };
eth.actions[ACTION_SCOREBOARD] = (ethAction_t){ 0, 0, "cg_draw2d 1; +scores\n", "-scores; cg_draw2d 0\n" };
eth.actions[ACTION_RELOAD] = (ethAction_t){ 0, 0, "+reload\n", "-reload\n" };
}
// Set an action if not already set.
void setAction(int action, int state) {
if (state && !eth.actions[action].state)
forceAction(action, state);
else if (!state && eth.actions[action].state)
forceAction(action, state);
}
// Use this with caution
void forceAction(int action, int state) {
if (state) {
eth.actions[action].state = 1;
syscall_CG_SendConsoleCommand(eth.actions[action].startAction);
#ifdef ETH_DEBUG
ethDebug("forceAction: %s", eth.actions[action].startAction);
#endif
} else {
eth.actions[action].state = 0;
syscall_CG_SendConsoleCommand(eth.actions[action].stopAction);
#ifdef ETH_DEBUG
ethDebug("forceAction: %s", eth.actions[action].stopAction);
#endif
}
}
void resetAllActions() {
int action;
for (action=0; action<ACTIONS_TOTAL; action++)
if (action != ACTION_SCOREBOARD)
forceAction(action, eth.actions[action].defaultState);
}
/*
==============================
Killing spree/stats/sound stuff
==============================
*/
// Spree sound
void playSpreeSound() {
if( !seth.value[VAR_SPREE_SOUNDS] )
return;
if ((eth.cg_time - eth.lastKillTime) < (SPREE_TIME * 1000)) {
// Define spree levels range - TODO: Dirty. find a better way to play with level range
typedef struct { int start; int end; } spreeLevel_t;
#define SPREE_LEVEL_SIZE 4
spreeLevel_t spreeLevels[SPREE_LEVEL_SIZE] = {
{ SOUND_DOUBLEKILL1, SOUND_PERFECT } , // Spree level 1
{ SOUND_GODLIKE1, SOUND_TRIPLEKILL },
{ SOUND_DOMINATING1, SOUND_ULTRAKILL3 },
{ SOUND_MONSTERKILL1, SOUND_WICKEDSICK } // Spree level 4
};
int spreeLevelMax = SPREE_LEVEL_SIZE - 1;
// Modify level+sound values to fit to spreeLevels_t and eth.sounds order
int level = eth.killSpreeCount - 2; // never '< 0' because first time here is with 2 kills
if (level > spreeLevelMax)
level = spreeLevelMax;
int levelSize = spreeLevels[level].end - spreeLevels[level].start;
int sound = (int)((float)(levelSize + 1) * rand() / (RAND_MAX + 1.0f));
sound += spreeLevels[level].start;
eth.spreelevel = sound;
eth.startFadeTime = eth.cg_time;
eth.s_level = level;
orig_syscall(CG_S_STARTLOCALSOUND, eth.sounds[sound], CHAN_LOCAL_SOUND, 230);
}
}
/* replaces tokens with correct value and returns pointer parsed string
[c] - current spree count
[v] - victim name
[n] - clean victim name
[t] - total kills
[m] - double/triple/multikill msg
[x] - Player XP
[p] - Player name
[M] - Mod name
[h] - Player health
[k] - Killer name
[K] - Clean killer name
[q] - amount of punkbuster screenshots requested
*/
char *Format(char *in){
char out[256];
memset(out, 0, sizeof(out));
int a, b, len = strlen(in);
for (a = 0, b = 0; a < len; a++) {
if ((a <= len-2) && (in[a] == '[' && in[a+2] == ']')) {
switch (in[a+1]) {
case 'v':
strncat(out, eth.VictimName, sizeof(out));
break;
case 'n':
strncat(out, Q_CleanStr(eth.VictimName), sizeof(out));
break;
case 't':
strncat(out, va("%i", eth.killCount), sizeof(out));
break;
case 'x':
strncat(out, va("%i", eth.cg_snap->ps.stats[STAT_XP]), sizeof(out));
break;
case 'q':
strncat(out, va("%i", eth.pbss), sizeof(out));
break;
case 'p':
strncat(out, eth.clientInfo[eth.cg_clientNum].name, sizeof(out));
break;
case 'M':
{
char gameMod[20];
syscall_CG_Cvar_VariableStringBuffer("fs_game", gameMod, sizeof(gameMod));
strncat(out, gameMod, sizeof(out));
break;
}
case 'k':
strncat(out, eth.KillerName, sizeof(out));
break;
case 'K':
{
char *c = strdup(eth.KillerName);
strncat(out, Q_CleanStr(c) , sizeof(out));
free(c);
break;
}
case 'h':
strncat(out, va("%i", eth.cg_snap->ps.stats[STAT_HEALTH]), sizeof(out));
break;
case 'c':
strncat(out, va("%i", eth.killCountNoDeath), sizeof(out));
break;
case '1': {
char *multikillmsg ;
if (eth.killSpreeCount == 2) {
multikillmsg = " ^1*** DOUBLEKILL***^7";
}
else if (eth.killSpreeCount == 3) {
multikillmsg = " ^1*** MULTIKILL***^7";
}
else if (eth.killSpreeCount == 4) {
multikillmsg = " ^1*** ULTRAKILL***^7";
}
else if (eth.killSpreeCount == 5) {
multikillmsg = " ^1*** MONSTERKILL***^7";
}
else if (eth.killSpreeCount > 5) {
multikillmsg = " ^1*** HOLY SHIT***^7";
}
else
break;
if (eth.killSpreeCount >= 2)
sprintf(out, "^2%s ^7was owned! %s ", eth.VictimName, multikillmsg);
break;
}
case '2': {
char *multikillmsg;
if (eth.killSpreeCount == 2) {
multikillmsg = "^1<!^7DOUBLEKILL^1!>";
}
else if (eth.killSpreeCount == 3) {
multikillmsg = "^1<!^7MULTIKILL^1!>";
}
else if (eth.killSpreeCount == 4) {
multikillmsg = "^1<!^7ULTRAKILL^1!>";
}
else if (eth.killSpreeCount > 4) {
multikillmsg = "^1<!^7MONSTERKILL^1!>";
}
else
break;
if (eth.killSpreeCount >= 2)
sprintf(out, "%s ", multikillmsg);
break;
}
case '3': {
char *multikillmsg;
if (eth.killSpreeCount == 2) {
multikillmsg = " ^7::: ^2Doublekill ^7:::";
}
else if (eth.killSpreeCount == 3) {
multikillmsg = " ^7::: ^2Multikill ^7:::";
}
else if (eth.killSpreeCount == 4) {
multikillmsg = " ^7::: ^2Ultrakill ^7:::";
}
else if (eth.killSpreeCount >= 5) {
multikillmsg = " ^7::: ^2Monsterkill ^7:::";
}
else
break;
if (eth.killSpreeCount >= 2)
sprintf(out, "%s ", multikillmsg);
break;
}
case 'e': {
char *msg;
if (eth.killCountNoDeath == 10) {
msg = "^7... is ^/tied for the lead! ^%(10 frags in a row)";
}
else if (eth.killCountNoDeath == 15) {
msg = "^7... has ^/taken the lead! ^%(15 frags in a row)";
}
else if (eth.killCountNoDeath == 20) {
msg = "^7... is on a ^/KILLING SPREE!!! ^%(20 frags in a row)";
}
else if (eth.killCountNoDeath == 25) {
msg = "^7... is ^/DOMINATING!!! ^%(25 frags in a row)";
}
else if (eth.killCountNoDeath == 30) {
msg = "^7... is on a ^/RAMPAGE!!! ^%(30 frags in a row)";
}
else
break;
if (eth.killCountNoDeath >= 2)
sprintf(out, "%s ", msg);
break;
}
case '6': {
char *killmsg;
int randmsg = rand() % 16;
if (eth.killCount) {
if (!randmsg)
killmsg = "^3 Let's Rock!!";
else if (randmsg == 1)
killmsg = "^3 Haha, Its a hole in Your head!";
else if (randmsg == 2)
killmsg = "^3 Eat my ass and God bless..";
else if (randmsg == 3)
killmsg = "^3 was soo weak and glassy-eyed";
else if (randmsg == 4)
killmsg = "^3, So I guess you’re not a fan of Eth";
else if (randmsg == 5)
killmsg = "^3 Give Me Your Soul";
else if (randmsg == 6)
killmsg = "^3 Once More, You Have to be the Grown-Up";
else if (randmsg == 7)
killmsg = "^3 Your Blood is soo Sweet, like marmalade";
else if (randmsg == 8)
killmsg = "^3 There is no God, no heaven, Just ME !!";
else if (randmsg == 9)
killmsg = "^3 Join Me in Hell, Won’t You?";
else if (randmsg == 10)
killmsg = "^3";
else if (randmsg == 11)
killmsg = "^3 I Am Your One-Way Ticket to Hell";
else if (randmsg == 12)
killmsg = "^3..How much is your dead body worth?...";
else if (randmsg == 13)
killmsg = "^3 Dead man walking? Not sure :)";
else if (randmsg == 14)
killmsg = "^3 Death Is Waiting 4 YOU!";
else if (randmsg == 15)
killmsg = "^3 Welcome to my list of fucked Bodies";
else if (randmsg == 16)
killmsg = "^3 Oh Yes, here is your Destination..";
else
killmsg = "^3 Time to Die. ";
}
else
break;
strncat(out,killmsg, sizeof(out));
break;
}
case 'R': {
char *msg;
if (eth.killCountNoDeath == 10) {
msg = "^3is on a ^2KILLING SPREE!!! ^3(10 frags in a row)";
}
else if (eth.killCountNoDeath == 15) {
msg = "^3is ^2DOMINATING!!! ^3(15 frags in a row)";
}
else if (eth.killCountNoDeath == 20) {
msg = "^3is on a ^2RAMPAGE!!! ^3(20 frags in a row)";
}
else if (eth.killCountNoDeath == 25) {
msg = "^3is ^2UNSTOPPABLE!!! ^3(25 frags in a row)";
}
else if (eth.killCountNoDeath == 30) {
msg = "^3is ^2WICKED SICK!!! ^3(30 frags in a row)";
}
else if (eth.killCountNoDeath == 35) {
msg = "^3is on a MEGA KILLINGSPREE!!! ^3(35 frags in a row)";
}
else if (eth.killCountNoDeath == 40) {
msg = "^3is OMFGHAXOR!!! ^3(40 frags in a row)";
}
else if (eth.killCountNoDeath == 45) {
msg = "^3I'M HARD AS FUCKING STEEL!!! ^3(45 frags in a row)";
}
else if (eth.killCountNoDeath == 50) {
msg = "^3NOBODY CAN STOP ME NOW!!! ^3(50 frags in a row)";
}
else
break;
if (eth.killCountNoDeath >= 2)
sprintf(out, "%s ", msg);
break;
}
case '5': {
char *multikillmsg;
int randmsg = rand() % 3;
if (eth.killSpreeCount == 2) {
if (!randmsg)
multikillmsg = " ^1-> ^7doubleLEAK!";
else if (randmsg == 1)
multikillmsg = " ^1-> ^7doubleLEAK!";
else
multikillmsg = " ^1-> ^7doubleLEAK!";
}
else if (eth.killSpreeCount == 3) {
if (!randmsg)
multikillmsg = " ^1-> ^7multiLEAK!";
else if (randmsg == 1)
multikillmsg = " ^1-> ^7multiLEAK!";
else
multikillmsg = " ^1-> ^7multiLEAK!";
}
else if (eth.killSpreeCount == 4) {
if (!randmsg)
multikillmsg = " ^1-> ^7ultraLEAK!";
else if (randmsg == 1)
multikillmsg = " ^1-> ^7ultraLEAK!";
else
multikillmsg = " ^1-> ^7ultraLEAK!";
}
else if (eth.killSpreeCount > 4) {
if (!randmsg)
multikillmsg = " ^1-> ^7monsterLEAK!";
else if (randmsg == 1)
multikillmsg = " ^1-> ^7Holy Shit!!!!!LEAK";
else
multikillmsg = " ^1-> ^7monsterLEAK!";
}
else
break;
strncat(out, multikillmsg, sizeof(out));
break;
}
case 'N': {
char *multikillmsg;
int randmsg = rand() % 3;
if (eth.killSpreeCount == 1) {
if (!randmsg)
multikillmsg = "EATEN";
else if (randmsg == 1)
multikillmsg = "OWNED";
else
multikillmsg = "ADIOS AMIGO";
}
if (eth.killSpreeCount == 2) {
if (!randmsg)
multikillmsg = "DOUBLE KILL";
else if (randmsg == 1)
multikillmsg = "PERFECT";
else
multikillmsg = "OWNED";
}
else if (eth.killSpreeCount == 3) {
if (!randmsg)
multikillmsg = "TRIPLE KILL";
else if (randmsg == 1)
multikillmsg = "GODLIKE";
else
multikillmsg = "LUDICROUS";
}
else if (eth.killSpreeCount == 4) {
if (!randmsg)
multikillmsg = "DOMINATING";
else if (randmsg == 1)
multikillmsg = "ULTRA KILL";
else
multikillmsg = "MEGA KILL";
}
else if (eth.killSpreeCount > 4) {
if (!randmsg)
multikillmsg = "WICKED SICK";
else if (randmsg == 1)
multikillmsg = "MONSTER KILL";
else
multikillmsg = "BOOM HEADSHOT";
}
else
break;
strncat(out, multikillmsg, sizeof(out));
break;
}
case 'X': {
char *killmsg;
int randmsg = rand() % 24;
if (eth.killCount) {
if (!randmsg)
killmsg = " ^7 + My Gun = +1 on my owned list.";
else if (randmsg == 1)
killmsg = "^7... What? There's only one of you?";
else if (randmsg == 2)
killmsg = " ^7 You're a joke!";
else if (randmsg == 3)
killmsg = "^7... suck it down!";
else if (randmsg == 4)
killmsg = " ^7, go home!";
else if (randmsg == 5)
killmsg = " ^7... Suprise, asshole!";
else if (randmsg == 6)
killmsg = "^7, shit happens.";
else if (randmsg == 7)
killmsg = "^7, you are the weakest link, good-bye!";
else if (randmsg == 8)
killmsg = "^7- Mmmm, bad case of lead poisoning!";
else if (randmsg == 9)
killmsg = " ^7is now in a better place!";
else if (randmsg == 10)
killmsg = " ^7 wanted to take part in my killingspree.";
else if (randmsg == 11)
killmsg = " ^7 enjoyed a ^3crisp ^7bullet to the head!";
else if (randmsg == 12)
killmsg = " ^7 is no more.";
else if (randmsg == 13)
killmsg = "^7, It's time to kick ass, and chew bubblegum... and i'm all outta gum.";
else if (randmsg == 14)
killmsg = "^7, it's time to abort your whole friggin' species.";
else if (randmsg == 15)
killmsg = "^7, Come get some.";
else if (randmsg == 16)
killmsg = " ^7... Get that crap outta here.";
else if (randmsg == 17)
killmsg = " ^7 got on the bad side of me... and ended up ^3DEAD^7!";
else if (randmsg == 18)
killmsg = "^7's brain made a mess on the floor... * clean up on isle";
else if (randmsg == 19)
killmsg = " ^7got in my way.";
else if (randmsg == 20)
killmsg = "^7... Eat shit and Die!";
else if (randmsg == 21)
killmsg = "^7, you suck.";
else if (randmsg == 22)
killmsg = "^7... Hehehe, what a mess.";
else if (randmsg == 23)
killmsg = "^7 was killed!";
else if (randmsg == 24)
killmsg = "^7, Looks like it's Time to Kill.";
else
killmsg = "^7 Time to Die.";
}
else
break;
strncat(out,killmsg, sizeof(out));
break;
}
case 'C': {
char *killmsg;
int randmsg = rand() % 12;
if (eth.killCountNoDeath) {
if (!randmsg)
killmsg = strncpy(ksFormat, " ^2...Suprise, Suprise, asshole^1!",sizeof(ksFormat));
else if (randmsg == 1)
killmsg = strncpy(ksFormat, " ^7You're a joke^1!",sizeof(ksFormat));
else if (randmsg == 2)
killmsg = strncpy(ksFormat, "^2... suck it down^1!",sizeof(ksFormat));
else if (randmsg == 3)
killmsg = strncpy(ksFormat, "^7, go home!",sizeof(ksFormat));
else if (randmsg == 4)
killmsg = strncpy(ksFormat, "^2...Suprise, Suprise, asshole^1!!",sizeof(ksFormat));
else if (randmsg == 5)
killmsg = strncpy(ksFormat, "^7, shit happens.",sizeof(ksFormat));
else if (randmsg == 6)
killmsg = strncpy(ksFormat, "^7 is now in a better place!",sizeof(ksFormat));
else if (randmsg == 7)
killmsg = strncpy(ksFormat, "^2 is no more^1.",sizeof(ksFormat));
else if (randmsg == 8)
killmsg = strncpy(ksFormat, "^7, Come get some^1.",sizeof(ksFormat));
else if (randmsg == 9)
killmsg = strncpy(ksFormat, "^7 got in my way.",sizeof(ksFormat));
else if (randmsg == 10)
killmsg = strncpy(ksFormat, "^2... Eat shit and ^1Die!",sizeof(ksFormat));
else if (randmsg == 11)
killmsg = strncpy(ksFormat, "^7, you suck.",sizeof(ksFormat));
else if (randmsg == 12)
killmsg = strncpy(ksFormat, "^2 was killed^1!",sizeof(ksFormat));
else
killmsg = strncpy(ksFormat, "^7 was killed^1!",sizeof(ksFormat));
}
else
break;
strncat(out, killmsg, sizeof(out));
break;
}
case 'P': {
char *multikillmsg;
if (eth.killSpreeCount == 2) {
multikillmsg = "^1<-- |DoubleKill|";
}
else if (eth.killSpreeCount == 3) {
multikillmsg = "^1<-- |MultiKill|";
}
else if (eth.killSpreeCount == 4) {
multikillmsg = "^1<-- |UltraKill|";
}
else if (eth.killSpreeCount > 4) {
multikillmsg = "^1<--|MonsterKill|";
}
else
break;
strncat(out, multikillmsg, sizeof(out));
break;
}
default:
break;
}
a += 2;
}
else
out[b] = in[a];
b = strlen(out);
}
strncpy(in,out,sizeof(out));
return in;
}
//tes: once per command call
int isCommandTime(void) {
static int lastTimeC;
if(seth.value[VAR_SNAPDELAY] != 0) {
if(lastTimeC + (int)seth.value[VAR_SNAPDELAY] > (eth.cg_time ))
return 0;
lastTimeC = eth.cg_time;
return 1;
}
// tes: so if set to 0 then we do it like this:
// count time delay for max commands we can send between snapshots
// this is strictly ping based and seems to be solution i search for :)
if((lastTimeC + (eth.cg_snap->ping/(CMD_BACKUP -1))) <= (eth.cg_time)){
lastTimeC = eth.cg_time;
return 1;
}
return 0;
}
void selfkillSpam() {
char send[256];
char msg[256];
strncpy(msg,skFormat,sizeof(msg));
snprintf(send, sizeof(send), "say \"%s\"\n", Format(msg));
syscall_CG_SendConsoleCommand(send);
}
// Customizable spam
void killSpam() {
char msg[256];
char send[256];
strncpy(msg,ksFormat,sizeof(msg));
snprintf(send, sizeof(send), "say \"%s\"\n", Format(msg));
syscall_CG_SendConsoleCommand(send);
}
void timenudge(int nTime) {
char send[256];
snprintf(send, sizeof(send), "cl_timenudge %d\n", nTime);
syscall_CG_SendConsoleCommand(send);
}
void deathSpam() {
char send[256];
char msg[256];
strncpy(msg,dieFormat,sizeof(msg));
snprintf(send, sizeof(send), "say \"%s\"\n", Format(msg));
syscall_CG_SendConsoleCommand(send);
}
// Auto demo record
void autoRecord() {
#define TMP_FILE_NAME "demo_in_progress"
static qboolean demoState = qfalse;
static int stateTime ;
int ethRate;
// Speed return if we don't want record demo
if (!demoState && !seth.value[VAR_RECDEMO])
return;
if ((eth.cg_snap->ps.eFlags != EF_DEAD)
&& (eth.cg_snap->ps.clientNum == eth.cg_clientNum)
&& (eth.clientInfo[eth.cg_clientNum].team != TEAM_SPECTATOR)
&& (eth.cg_snap->ps.stats[STAT_HEALTH] > 0)
&& (eth.cg_snap->ps.pm_flags != PMF_FOLLOW)
&& seth.value[VAR_RECDEMO]
&& !demoState) {
stateTime=0 ;
// FIXME: check if a tmp demo file already exist
syscall_CG_SendConsoleCommand("record " TMP_FILE_NAME "\n");
stateTime = eth.cg_time;
#ifdef ETH_DEBUG
ethDebug("demo: start");
#endif
demoState = qtrue;
} else if (((eth.cg_snap->ps.eFlags == EF_DEAD)
|| (eth.cg_snap->ps.clientNum != eth.cg_clientNum)
|| (eth.clientInfo[eth.cg_clientNum].team == TEAM_SPECTATOR)
|| (eth.cg_snap->ps.stats[STAT_HEALTH] <= 0)
|| (eth.cg_snap->ps.pm_flags == PMF_FOLLOW)
|| (!seth.value[VAR_RECDEMO]))
&& demoState) {
char buffFrom[MAX_OSPATH];
char buffTo[MAX_OSPATH];
// Get fsgame
char fsGame[MAX_QPATH];
syscall_CG_Cvar_VariableStringBuffer("fs_game", fsGame, sizeof(fsGame));
// Get current time
time_t ethTime = time(NULL);
struct tm *localTime = localtime(ðTime);
orig_Cbuf_ExecuteText(EXEC_NOW, "stoprecord\n");
stateTime = ((eth.cg_time - stateTime)/1000) ;
ethRate=(int)((((float)eth.autoDemoKillCount/(float)stateTime)*100.0f)/(float)(0.2)) ;
#ifdef ETH_DEBUG
ethDebug("demo: final stateTime:[%i]", stateTime) ;
ethDebug("demo: kill acc:[%i]",ethRate);
ethDebug("demo: stop");
#endif
// buffForm = /homepath/fsgame/
syscall_CG_Cvar_VariableStringBuffer("fs_homepath", buffFrom, sizeof(buffFrom));
sprintf(buffFrom, "%s/%s/demos/", buffFrom, fsGame);
strncpy(buffTo, buffFrom, sizeof(buffFrom));
// buffForm = /homepath/fsgame/demos/demoinprogress
strcat(buffFrom, TMP_FILE_NAME ".dm_");
// Contruct final file name, buffTo = /homepath/fsgame/demo/aaaa_mm_dd_hhmmss_mod_map_killcount
sprintf(buffTo,"%s%i-%.2i-%.2i-%.2i%.2i%.2i_%s_%s_%ikills_%isec_%irate.dm_", buffTo, localTime->tm_year + 1900, localTime->tm_mon + 1,
localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec, fsGame,
eth_Info_ValueForKey(eth.cgs_gameState->stringData + eth.cgs_gameState->stringOffsets[CS_SERVERINFO], "mapname"),
eth.autoDemoKillCount, stateTime, ethRate);
// Version of the demo
if (!strcmp(sethET->version, "2.55")){
strcat(buffFrom, "82");
strcat(buffTo, "82");
} else if(!strcmp(sethET->version, "2.56")){
strcat(buffFrom, "83");
strcat(buffTo, "83");
} else {
strcat(buffFrom, "84");
strcat(buffTo, "84");
}
#ifdef ETH_DEBUG
ethDebug("demo: got %i kills, need %i kills", eth.autoDemoKillCount, (int)seth.value[VAR_RECDEMO]);
#endif
// If we more than kills threshold then rename the demo
if (eth.autoDemoKillCount >= seth.value[VAR_RECDEMO]) {
#ifdef ETH_DEBUG
ethDebug("demo: move [%s] to [%s]", buffFrom, buffTo);
#endif
rename(buffFrom, buffTo);
// Else delete it
} else {
#ifdef ETH_DEBUG
ethDebug("demo: delete [%s]", buffFrom, buffTo);
#endif
unlink(buffFrom);
}
eth.autoDemoKillCount = 0;
demoState = qfalse;
}
}
/*
==============================
et guid
==============================
*/
// Init cl_guid by environnement var
void loadCL_GUID(void) {
char *cl_guid = getenv("CLGUID");
if (cl_guid) {
syscall_CG_Cvar_Set("cl_guid", cl_guid);
// Delete env var so cl_guid is set once, and not each cg_init
unsetenv("CLGUID");
}
}
void doMusicSpam() {
static char oldTitle[MAX_STRING_CHARS];
static qboolean firstTime = qtrue;
char *artist,*currentTime,*totalTime,*title;
artist=currentTime=totalTime=title=NULL;
if( firstTime ){
oldTitle[0] = '\0';
firstTime = qfalse;
return;
}
if( seth.value[VAR_MUSICSPAM]==1 )
title = strdup(getOutputSystemCommand("dcop amarok player title"));
else if (seth.value[VAR_MUSICSPAM]==2)
title = strdup(getOutputSystemCommand("xmmsctrl print %T"));
else
return;
if( strcmp(title,oldTitle) ){ //new song
char msg[MAX_STRING_CHARS];
strncpy(oldTitle,title,MAX_STRING_CHARS);
if( seth.value[VAR_MUSICSPAM]==1 ){
artist = strdup(getOutputSystemCommand("dcop amarok player artist"));
currentTime = strdup(getOutputSystemCommand("dcop amarok player currentTime"));
totalTime = strdup(getOutputSystemCommand("dcop amarok player totalTime"));
} else if( seth.value[VAR_MUSICSPAM]==2 ) {
artist = NULL; // no artist print in xmmsctrl?? wtf?
currentTime = strdup(getOutputSystemCommand("xmmsctrl print %m"));
totalTime = strdup(getOutputSystemCommand("xmmsctrl print %M"));
}
if( artist ){
sprintf(msg,"say \"^oPlaying ^0[^w%s - %s^0]^*-^0[^w%s/%s^0]\"\n", artist, title, currentTime, totalTime);
free(artist);
} else
sprintf(msg,"say \"^oPlaying ^0[^w%s^0]^*-^0[^w%s/%s^0]\"\n", title, currentTime, totalTime);
syscall_CG_SendConsoleCommand(msg);
free(currentTime);
free(totalTime);
}
free(title);
}