PDA

View Full Version : Weapon functions (+ setMoveSpeedScale)



Mitch
6th March 2015, 16:45
I have been adding weapon related functions to my libcod git the last few weeks.

Also I found out how the weapons use their move speed scale. So i added this cod4 function to cod2 :D.

player SetMoveSpeedScale(2.5)
Note: you need to reset the value manual. It doesn't automatically revert back to 1 when the player disconnects or the map restarts.



init()
{
setdefaultweapon("mp44_mp"); // changes defaultweapon_mp to mp44_mp

level.otherweapons = []; // for weapons that aren't stored in level.weapons
level.otherweapons["glock_mp"] = spawnstruct();

loadedweapons = getloadedweapons();
developer = getCvarInt("developer_script");
for(i=0;i<loadedweapons.size;i++)
{
weaponname = loadedweapons[i]; // i = weapon index
if(isDefined(level.weapons[weaponname]))
loadWeaponInfo(i, level.weapons[weaponname]);
else if(isDefined(level.otherweapons[weaponname]))
loadWeaponInfo(i, level.otherweapons[weaponname]);

if(developer == 1 || i >= 64)
printfline("[%]: %", i, weaponname);
}

setWepDamage("glock_mp", 65, true);
setWepMeleeDamage("raygun_m2_mp", 400, true);
}


I made these wrappers to make the function easier and less messy.


loadWeaponInfo(i, array)
{
array.id = i;
array.dmg = getweapondamage(i); // store baseline
array.meleedmg = getweaponmeleedamage(i); // in case you want to restore old value

if(i >= 64) // no viewmodels after 64th weapon
array.bugged = 1;
}

getWeaponArray(weapon)
{
if(isDefined(level.weapons[weapon]) && isDefined(level.weapons[weapon].id))
return level.weapons[weapon];
else if(isDefined(level.otherweapons[weapon]) && isDefined(level.otherweapons[weapon].id))
return level.otherweapons[weapon];
else
return undefined;
}

updateWepDamage(weapon, dmg)
{
array = getWeaponArray(weapon);
if(isDefined(array))
array.dmg = dmg;
}

updateWepMeleeDamage(weapon, dmg)
{
array = getWeaponArray(weapon);
if(isDefined(array))
array.meleedmg = dmg;
}

getWeaponId(weapon)
{
if(isDefined(level.weapons[weapon]) && isDefined(level.weapons[weapon].id))
return level.weapons[weapon].id;
else if(isDefined(level.otherweapons[weapon]) && isDefined(level.otherweapons[weapon].id))
return level.otherweapons[weapon].id;
else
return -1;
}

WeaponMaxAmmo(weapon)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

return getweaponmaxammo(id);
}

WeaponDamage(weapon)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

return getweapondamage(id);
}

WeaponMeleeDamage(weapon)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

return getweaponmeleedamage(id);
}

setWepDamage(weapon, dmg, isdefault)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

if(isDefined(isdefault) && isdefault)
updateWepDamage(weapon, dmg);

return setweapondamage(id, dmg);
}

setWepMeleeDamage(weapon, dmg, isdefault)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

if(isDefined(isdefault) && isdefault)
updateWepMeleeDamage(weapon, dmg);

return setweaponmeleedamage(id, dmg);
}


I haven't found where cod stored the hit location multiplier yet. You can check the bottom of gsc_utils.cpp (https://github.com/M-itch/libcod/blob/master/gsc_utils.cpp) to see what i mapped so far.
Is there any function related to weapon that you would like?

Edit: forgot one example (i copied the cod4 name)


maxammo = WeaponMaxAmmo("mp44_mp");

Ni3ls
6th March 2015, 22:33
Reloadtime, firetime and melee time maybe?

Mitch
7th March 2015, 09:19
Reloadtime, firetime and melee time maybe?

I tried firetime, but i don't get the exact values as in the weapon files back and when i change the value it bugs your weapon. Also it has no affect on your fire speed.

Edit: read value: 7.00649e-44, actual firetime: 0.05.
Edit 2: It looks like firetime is not a float, but a integer.
Edit 3: it works now. CoD2 saves firetime multiplied by 1000. So 0.05 is 50.

http://classic.xfire.com/video/6335c5/



sayOrUpdateFireTime(args)
{
if(args.size >= 3) // say !firetime time
{
firetime = Int(args[2]);
maps\mp\gametypes\_weapons::setWepFireTime(self getCurrentWeapon(), firetime);
}
else
{
firetime = maps\mp\gametypes\_weapons::WeaponFireTime(self getCurrentWeapon());
maps\mp\gametypes\_util::tellMessage("FireTime: " + firetime);
}
}



WeaponFireTime(weapon)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

return getweaponfiretime(id);
}

setWepFireTime(weapon, time)
{
id = getWeaponId(weapon);
if(id == -1)
return 0;

return setweaponfiretime(id, time);
}

Ni3ls
7th March 2015, 13:50
Nice work! And what about the others? Im very curious right now :0

Mitch
7th March 2015, 14:48
Nice work! And what about the others? Im very curious right now :0

Thank you. But i'm gonna try those a other time.
Finding the right offset is very easy. It works exactly as how you find the 'closer' function. But instead of getting a function you have a hex value as offset. (press D a few times until you see ...h then google 0x... to decimal)

Changing the firetime doesn't always change how fast you can fire. For some weapons it doesn't work.

I committed my changes. https://github.com/M-itch/libcod/commit/8b60707edb44fcd7bb91f853950f04c343e27dff

IzNoGoD
5th May 2015, 16:07
The big problem with movespeedscale is that it does not influence the acceleration in air.
I finally finished a patch that allows that (player set_g_speed(210))

Mitch, ring me up on xfire for the code :)

filthy_freak_
20th May 2015, 00:15
Is it possible to set melee damage per client? I'm working on a sprinting code that does not change your weapon or use modified weapon files. Only roadblock is disabling melee while sprinting.

Tally
20th May 2015, 07:25
Is it possible to set melee damage per client? I'm working on a sprinting code that does not change your weapon or use modified weapon files. Only roadblock is disabling melee while sprinting.

Nope. Very few weapon attributes can be set with script. Melee is not one of them. I have no idea if Libcod can set it.

Mitch
20th May 2015, 07:37
Nope. Very few weapon attributes can be set with script. Melee is not one of them. I have no idea if Libcod can set it.

I think setting the damage per client won't be easy. But it is doable to set the delay time until the next bash.
Basically blocking the melee for a short time. (It might cause side effects e.g. unable to fire either)

filthy_freak_
20th May 2015, 09:29
I think setting the damage per client won't be easy. But it is doable to set the delay time until the next bash.
Basically blocking the melee for a short time. (It might cause side effects e.g. unable to fire either)

Hmm, being unable to shoot while sprinting won't be a problem. If you managed to do this it would be great.

Also, here is the sprint code i'v done. Credits to Iznogod for the base, Tally for the HUD and mitch for setg_speed.


init()
{
if(getCvarInt("serv_disable_sprint") != 1)
{
precacheShader("gfx/hud/hud@health_back.tga");
precacheShader("gfx/hud/hud@health_bar.tga");

level thread onPlayerConnect();
}
}

onPlayerConnect()
{
level endon("intermission");

for(;;)
{
level waittill("connecting", player);

player thread waitforspawn();
}
}

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

for(;;)
{
self waittill("spawned_player");

self thread onPlayerSpawn();
}
}

onPlayerSpawn()
{
level endon("intermission");
self endon("disconnect");
self endon("killed_player");

sprinting = false;
speed = getCvarInt("g_speed");
self setg_speed(speed);
maxStamina = 83;
minStamina = 15;
stamina = maxStamina;
sprintScale = 1.6;

current = "";
clip = 0;
clipb = 0;
ammo = 0;
ammob = 0;
weapon1 = "";
weapon2 = "";
currentSlot = "";

if(!isDefined(self.sprint_hud_back)) {
self.sprint_hud_back = newClientHudElem( self );
self.sprint_hud_back setShader("gfx/hud/hud@health_back.tga", stamina + 2, 5);
self.sprint_hud_back.horzAlign = "right";
self.sprint_hud_back.vertAlign = "bottom";
self.sprint_hud_back.x = -93;
self.sprint_hud_back.y = -49;
}
if(!isDefined(self.sprint_hud)) {
self.sprint_hud = newClientHudElem( self );
self.sprint_hud setShader("gfx/hud/hud@health_bar.tga", stamina, 3);
self.sprint_hud.color = ( 0, 0, 1);
self.sprint_hud.horzAlign = "right";
self.sprint_hud.vertAlign = "bottom";
self.sprint_hud.x = -92;
self.sprint_hud.y = -48;
}

while(isAlive(self))
{
if(self useButtonPressed() && !sprinting && (self forwardbuttonpressed() - self backbuttonpressed() + self leftbuttonpressed() - self rightbuttonpressed() != 0) && self GetStance() == "stand" && !self isAiming())
{
if(stamina > minStamina)
{
sprinting = true;

current = self getCurrentWeapon();
weapon1 = self getWeaponSlotWeapon("primary");
weapon2 = self getWeaponSlotWeapon("primaryb");

if(current == weapon1) currentSlot = "primary";
else currentSlot = "primaryb";

if(currentSlot == "none") continue;

clip = self getWeaponSlotClipAmmo("primary");
ammo = self getWeaponSlotAmmo("primary");
clipb = self getWeaponSlotClipAmmo("primaryb");
ammob = self getWeaponSlotAmmo("primaryb");

if(currentSlot == "primary")
self takeWeapon(weapon2);
else self takeWeapon(weapon1);

self setWeaponSlotClipAmmo(currentSlot, 0);
self setWeaponSlotAmmo(currentSlot, 0);
self setg_speed(int(speed * sprintScale));
}
else if(stamina < maxStamina)
{
stamina++;
self.sprint_hud setShader("gfx/hud/hud@health_bar.tga", stamina, 3);
}
}
else if(self useButtonPressed() && (self forwardbuttonpressed() - self backbuttonpressed() + self leftbuttonpressed() - self rightbuttonpressed() != 0) && self GetStance() == "stand" && !self isAiming())
{
//continue sprinting
stamina--;
self.sprint_hud setShader("gfx/hud/hud@health_bar.tga", stamina, 3);
if(stamina <= 0)
{
sprinting = false;
stamina = 0;

if(currentSlot == "primary")
self setWeaponSlotWeapon("primaryb", weapon2);
else self setWeaponSlotWeapon("primary", weapon1);

self setWeaponSlotClipAmmo("primary", clip);
self setWeaponSlotAmmo("primary", ammo);
self setWeaponSlotClipAmmo("primaryb", clipb);
self setWeaponSlotAmmo("primaryb", ammob);
self setg_speed(speed);
}
}
else if(sprinting)
{
sprinting = false;

if(stamina < 0)
stamina = 0;

if(currentSlot == "primary")
self setWeaponSlotWeapon("primaryb", weapon2);
else self setWeaponSlotWeapon("primary", weapon1);

self setWeaponSlotClipAmmo("primary", clip);
self setWeaponSlotAmmo("primary", ammo);
self setWeaponSlotClipAmmo("primaryb", clipb);
self setWeaponSlotAmmo("primaryb", ammob);
self setg_speed(speed);
}
else
{
if(stamina < maxStamina)
{
stamina++;
self.sprint_hud setShader("gfx/hud/hud@health_bar.tga", stamina, 3);
}
}
wait 0.05;
}
}

isAiming()
{
if(self playerads() > 0)
return true;
else
return false;
}


Just call init(); on gametype startup.

filthy_freak_
20th May 2015, 09:31
Also speaking of weapon functions - how about a proper isHoldingNade(); function?

IzNoGoD
20th May 2015, 12:12
http://modsonline.com/Forums-top-152632-0.html

filthy_freak_
20th May 2015, 12:23
http://modsonline.com/Forums-top-152632-0.html

Requires editing weaponfile?

filthy_freak_
20th May 2015, 23:55
Here are the addresses required to get setg_speed working on 1.0


//libcod.cpp
#if COD_VERSION == COD2_1_0
cracking_hook_call(0x080F50AB, (int)hook_player_g_speed);
#elif COD_VERSION == COD2_1_3
cracking_hook_call(0x080F7803, (int)hook_player_g_speed);

//gsc_player.cpp
#if COD_VERSION == COD2_1_0
calc_client_speed_t calc_client_speed = (calc_client_speed_t)0x0811FB7A;
#else
calc_client_speed_t calc_client_speed = (calc_client_speed_t)0x0812200A;
#endif

Mitch
21st May 2015, 07:11
Here are the addresses required to get setg_speed working on 1.0

I added them last night and included 1.2. I was working on changing g_gravity per player :).

https://github.com/M-itch/libcod/commit/6dee9a7d9b12b8f0ba7f4ec360dac4ef9608efb7

Edit: this should block melee and fire for x time (in ms).


void gsc_player_setweaponfiremeleedelay(int id) {
int delay;
if ( ! stackGetParams("i", &delay)) {
printf("scriptengine> ERROR: gsc_player_setweaponfiremeleedelay(): param \"delay\"[1] has to be an int!\n");
stackPushUndefined();
return;
}

if(delay < 0) {
printf("scriptengine> ERROR: gsc_player_setweaponfiremeleedelay(): param \"delay\"[1] must be equal or above zero!\n");
stackPushUndefined();
return;
}

int* weapondelay = (int *)(PLAYERSTATE(id) + 0x34);
*weapondelay = delay;
}

filthy_freak_
21st May 2015, 17:42
Edit: this should block melee and fire for x time (in ms).

Doesn't work for me after adding above code to gsc_player.cpp & adding command to gsc.cpp.

self setweaponfiremeleedelay(delayinms); doesn't seem to have an effect.

Mitch
21st May 2015, 18:52
Doesn't work for me after adding above code to gsc_player.cpp & adding command to gsc.cpp.

self setweaponfiremeleedelay(delayinms); doesn't seem to have an effect.

It does work for me, but you first need to bash once and then melee is blocked. But I should be able to fix that.



while(isAlive(self))
{
self setweaponfiremeleedelay(1000); // keep forcing 1s delay

if(self MeleeButtonPressed() && self UseButtonPressed())
{
break;
}

wait(0.05);
}

filthy_freak_
21st May 2015, 19:47
It does work for me, but you first need to bash once and then melee is blocked. But I should be able to fix that.



while(isAlive(self))
{
self setweaponfiremeleedelay(1000); // keep forcing 1s delay

if(self MeleeButtonPressed() && self UseButtonPressed())
{
break;
}

wait(0.05);
}


Yep it was an error on my side not forcing the delay. Works fine except for the first bash like you described.

Mitch
21st May 2015, 20:47
Yep it was an error on my side not forcing the delay. Works fine except for the first bash like you described.

I fixed the first bash problem. In addition to blocking firing, it also blocks aiming and reloading your weapon and it delays switching your weapon.

https://github.com/M-itch/libcod/commit/c3889453ffce5df9b10f3eb043a4f6d86ac2ce74

filthy_freak_
22nd May 2015, 14:02
I fixed the first bash problem. In addition to blocking firing, it also blocks aiming and reloading your weapon and it delays switching your weapon.

https://github.com/M-itch/libcod/commit/c3889453ffce5df9b10f3eb043a4f6d86ac2ce74

Nice, previous bug is resolved. Found another though - if setweaponfiremeleedelay gets called on you while you are doing a weapon animation (Shooting, bashing) it will repeat the animation.

Mitch
22nd May 2015, 14:57
Found another though - if setweaponfiremeleedelay gets called on you while you are doing a weapon animation (Shooting, bashing) it will repeat the animation.

You could read the delay value and only start sprinting after the value has reached 0.
(When the value is above 0 then the player has a weapon animation running)

Ni3ls
3rd September 2015, 09:11
Sorry for bump, but im really interest in this. So for now you get damage, meleedamage, firetime and speed working?

EDIT: You added it here: https://github.com/M-itch/libcod/commit/8b60707edb44fcd7bb91f853950f04c343e27dff
I must add all the green and red parts to my own gsc.cpp and gsc_utils.cpp and then compile it?

IzNoGoD
3rd September 2015, 10:26
Sorry for bump, but im really interest in this. So for now you get damage, meleedamage, firetime and speed working?

EDIT: You added it here: https://github.com/M-itch/libcod/commit/8b60707edb44fcd7bb91f853950f04c343e27dff
I must add all the green and red parts to my own gsc.cpp and gsc_utils.cpp and then compile it?

or just download the modified file...

Ni3ls
3rd September 2015, 10:50
And then compile with that /doit command or will it auto load if I start a server?

kung foo man
3rd September 2015, 19:40
In C there is like nothing automatic, at every change to the C code you need a rebuild (./doit.sh base; ./doit.sh cod2_1_0) and a server restart. Probably the server might even crash, when the .so is still in memory of a process and then overwritten.

Ni3ls
4th September 2015, 13:44
But also the red parts? Or just the green ones?

kung foo man
5th September 2015, 00:38
red = removed stuff, green = added stuff

Just clone the whole repo and build it:



cd /ur/cod2/path
git clone https://github.com/M-itch/libcod
cd libcod
./doit.sh base
./doit.sh cod2_1_0
# now set ur LD_PRELOAD path to libcod/bin/cod2_1_2.so

Paho
17th January 2016, 12:09
level.weapons["greasegun_mp"].id=1;
self iprintlnbold(getweaponmeleedamage(1));
outpoot: 150 it's default values mp gametypes, mod attribute: 400. What's problems?
how change melee damage?

self setweapondamagemelee(1,999999);
outpoot: unknown function
Help me pls :eek:

IzNoGoD
17th January 2016, 12:12
You cannot just query weapon 1 if you set the .id=1 in gsc. You need to use

loadedweapons = getloadedweapons();

Second point: self is probably not a player.

Paho
17th January 2016, 12:22
self setweapondamagemelee(1,999999);

second miss setweapondamagemelee need setweaponmeleedamage xD tnx for first sulution

Paho
6th February 2016, 22:16
this global function's only for all weapons on map? there are ways for a client(self)?

Mitch
7th February 2016, 09:50
this global function's only for all weapons on map? there are ways for a client(self)?

It is global. There is no way to set them for each client in libcod.
However I thought it was possible to hook the function where each player loads the damage for the weapon.
Also you can modify the damage each player does in the damage callback.

Paho
7th February 2016, 10:14
I meaned gunmodel for example
how to set model in 1thPerson?(scripts)
in 3th - attach

Paho
10th February 2016, 09:26
How can change weapon model in 1thirdPerson(1Face) with scripts using usual PrecacheModel(don't PrecacheItem)?