Player movement & grenades.
Usage:
player setWalkDir(string); //Set the walk direction for a player/bot. Very similar to moveTo() but accounts for collision!
player setWalkAngle(int); //Same as setWalkDir(string) but allows more configuration.
player setWepType(string); //This is to fix bot shooting with rifle weapons. Not needed if someone made a func to grab your current weapon type via libcod.
player throwNade(bool); //Holds grenade while true, then throws it after changing to false. Untested on real clients, works fine with bots.
player getCookTime(); //Returns time left until grenade explodes while cooking grenade. Can also be used to detect whether player is holding a grenade.
It may also be possible to make funcs such as playerShoot, playerADS, changeStance etc. with a little more tweaking and testing.
PHP Code:
onPlayerConnect()
{
self setWalkDir("none");
self setWepType("none");
}
doPlayerMovement()
{
self setWalkDir("forward");
self setWalkAngle(127); //Forward
self setWalkDir("back");
self setWalkAngle(129); //Back
self setWalkDir("right");
self setWalkAngle(127 << 8); //Right
self setWalkDir("left");
self setWalkAngle(129 << 8); //Left
self setWalkAngle((129 << 8) | 127); //Left + forward (Untested)
self setWalkDir("none");
}
playThrowNade()
{
if(!self getCookTime()) //Not currently holding nade
self throwNade(true);
wait 3;
self throwNade(false);
}
}
weaponSetup()
{
//Only needed if you wish to make bots work with stock weapons.
if(self getcurrentweapon() == "kar98k_rifle_mp")
self setWepType("rifle");
else
self setWepType("none");
}
Installation
Open libcod.cpp, add;
PHP Code:
int client_movement[64] = {0};
int bot_shoot[64] = {0};
int bot_wepType[64] = {0};
int bot_throwNade[64] = {0};
cHook *hook_play_movement;
int play_movement(int a1, int a2)
{
#if COD_VERSION == COD2_1_0
int offset = 0x841FB0C;
#elif COD_VERSION == COD2_1_2
int offset = 0x842200C;
#elif COD_VERSION == COD2_1_3
int offset = 0x842308C;
#else
#warning play_movement() got no working addresses
int offset = 0x0;
#endif
extern int playerinfo_base, playerinfo_size;
int addrtype, clientnum;
clientnum = (a1 - *(int*)offset) / playerinfo_size;
if(*(int*)(*(int*)playerinfo_base + clientnum * playerinfo_size) == 4)
{
addrtype = gsc_libcod_getAddressType(clientnum);
if(addrtype == 0) //bot stuff here
{
if(!bot_throwNade[clientnum])
{
if(!bot_wepType[clientnum])
{
if(bot_shoot[clientnum] == 4097)
bot_shoot[clientnum] = 0;
else
bot_shoot[clientnum] = 4097;
} else
bot_shoot[clientnum] = 4097;
} else {
bot_shoot[clientnum] = 65536;
}
*(int *)(a2 + 4) = bot_shoot[clientnum];
if(!client_movement[clientnum])
*(int *)(a2 + 24) = 0;
else
*(int *)(a2 + 24) = client_movement[clientnum];
} else { //player stuff here
if(client_movement[clientnum])
*(int *)(a2 + 24) = client_movement[clientnum];
}
}
hook_play_movement->unhook();
int (*sig)(int a1, int a2);
*(int *)&sig = hook_play_movement->from;
int ret = sig(a1, a2);
hook_play_movement->hook();
return ret;
}
Also add the following at the correct location in libcod.cpp;
PHP Code:
//1.0
hook_play_movement = new cHook(0x0808F488, (int)play_movement);
hook_play_movement->hook();
//1.2
hook_play_movement = new cHook(0x08090D18, (int)play_movement);
hook_play_movement->hook();
//1.3
hook_play_movement = new cHook(0x08090DAC, (int)play_movement);
hook_play_movement->hook();
Open gsc_player.cpp and add the following;
PHP Code:
void gsc_player_set_walkdir(int id)
{
char* walkDir;
if ( ! stackGetParams("s", &walkDir)) {
printf("scriptengine> ERROR: gsc_player_set_walkdir(): param \"walkDir\"[1] has to be an string!\n");
stackPushUndefined();
return;
}
extern int client_movement[64];
if(!strcmp(walkDir, "none"))
client_movement[id] = (0);
else if(!strcmp(walkDir, "forward"))
client_movement[id] = (127);
else if(!strcmp(walkDir, "back"))
client_movement[id] = (129);
else if(!strcmp(walkDir, "right"))
client_movement[id] = (127 << 8);
else if(!strcmp(walkDir, "left"))
client_movement[id] = (129 << 8);
}
void gsc_player_set_walkangle(int id)
{
int walkDir;
if ( ! stackGetParams("i", &walkDir)) {
printf("scriptengine> ERROR: gsc_player_set_walkangle(): param \"walkDir\"[1] has to be an int!\n");
stackPushUndefined();
return;
}
extern int client_movement[64];
if(!walkDir)
client_movement[64] = (0);
else
client_movement[64] = (walkDir);
}
void gsc_player_set_weptype(int id)
{
char* wepType;
if ( ! stackGetParams("s", &wepType)) {
printf("scriptengine> ERROR: gsc_player_set_weptype(): param \"wepType\"[1] has to be an string!\n");
stackPushUndefined();
return;
}
extern int bot_wepType[64];
if(!strcmp(wepType, "rifle"))
bot_wepType[id] = (0);
else
bot_wepType[id] = (1);
}
void gsc_player_thrownade(int id)
{
int throwNade;
if ( ! stackGetParams("i", &throwNade)) {
printf("scriptengine> ERROR: thrownade(): param \"throwNade\"[1] has to be an int!\n");
stackPushUndefined();
return;
}
extern int bot_throwNade[64];
bot_throwNade[id] = (throwNade);
}
void gsc_player_getcooktime(int id) {
int nadetime = PLAYERSTATE(id) + 60;
if(*(int*)nadetime)
stackPushInt(*(int*)nadetime);
else
stackPushInt(0);
}
Open gsc_player.hpp and add the following;
PHP Code:
void gsc_player_set_walkdir(int id);
void gsc_player_set_walkangle(int id);
void gsc_player_set_weptype(int id);
void gsc_player_thrownade(int id);
void gsc_player_getcooktime(int id);
Open gsc.cpp and add the following in the correct location;
PHP Code:
{"setwalkdir" , gsc_player_set_walkdir , 0},
{"setwalkangle" , gsc_player_set_walkangle , 0},
{"setweptype" , gsc_player_set_weptype , 0},
{"thrownade" , gsc_player_thrownade , 0},
{"getcooktime" , gsc_player_getcooktime , 0},
Compile and you are done.
Note: Adding this will fix a few bugs with bots. If using setWepType, stock weapons will work with bots correctly. Also this automatically fixes a bug with bot torso/legs being out of alignment.