PDA

View Full Version : WCS Investigation



ZERO
06-26-2012, 11:07 PM
I am looking over the sourcecode for the core of the original wcs mod so that I can better understand the differences between that one and ours. This will allow me to possibly find things that may need to be fixed that we are not doing correctly.

So here is the findings:


// after this time (plus freezetime), ultimates can be used
"wcs_cfg_ulti_warmup" "10"
We currently do not have any default limit such as this...


// help for new players, give that levels
"wcs_cfg_newplayerbonus" "5"
We do not currently give free levels for first time players


// shotgun penalty, give that value in % less chance to activate player_hurt skills
"wcs_cfg_shotgunchance" "30"
This does not exist and should not be needed b/c of the way the OB update fucked shotguns


// take XP on using "resetskills", number in percent of current level XP
"wcs_cfg_resetskillspenalty" "10"
As the ranking uses xp we try to avoid at all costs taking xp from a player. Perhaps some sort of decrease on xp awards for the next X kills or something would balance it out? Could reduce xp awarded for the next 20 kills by 10% or something...

Here is the exact longjump code from the original:

if (server_var(wcs_longjump) != "0") do
{
if (server_var(wcs_longjump) < 1) then es_xset wcs_longjump 1
// calculate the new velocy for jumping
es_getplayerprop wcs_tmp event_var(userid) CCSPlayer.baseclass.localdata.m_vecVelocity[0]
es_math wcs_tmp * server_var(wcs_longjump)
es_getplayerprop wcs_tmp1 event_var(userid) CCSPlayer.baseclass.localdata.m_vecVelocity[1]
es_math wcs_tmp1 * server_var(wcs_longjump)
es_format wcs_tmp "%1,%2,0" server_var(wcs_tmp) server_var(wcs_tmp1)
es_setplayerprop event_var(userid) CBasePlayer.localdata.m_vecBaseVelocity server_var(wcs_tmp)
}
}
}
This is exactly what our races do now but we divide the multiplier effect by 2 first. However I have now found many sm plugins that use long jump multiplying by .25 instead of dividing by 2 like I do. This is the equlivlant of dividing by 4 which is similar to the divider value for the python jack. Solution is to change to multiply by .25 to correct the issue.

The following method runs every .1 second to process weapon restrections. Optimizations to this method may correct some bugs: (from War3Source_Engine_Weapon)

public Action:DeciSecondTimer(Handle:h,any:a){
timerskip--;
if(timerskip<1){
timerskip=10;
for(new client=1;client<=MaxClients;client++){
/*if(true){ //test
new wpnent = GetCurrentWeaponEnt(client);
if(FindSendPropOffs("CWeaponUSP","m_bSilencerOn")>0){

SetEntData(wpnent,FindSendPropOffs("CWeaponUSP","m_bSilencerOn"),true,true);
}

}*/

if(hasAnyRestriction[client]&&ValidPlayer(client,true)){

new String:name[32];
GetClientName(client,name,sizeof(name));
//PrintToChatAll("ValidPlayer %d",client);

new wpnent = GetCurrentWeaponEnt(client);
//PrintIfDebug(client," weapon ent %d %d",client,wpnent);
//new String:WeaponName[32];

//if(IsValidEdict(wpnent)){

// }

//PrintIfDebug(client," %s res: (%s) weapon: %s",name,weaponsAllowed[client],WeaponName);
// if(strlen(weaponsAllowed[client])>0){
if(wpnent>0&&IsValidEdict(wpnent)){


if (CheckCanUseWeapon(client,wpnent)){
//allow
}
else
{
//RemovePlayerItem(client,wpnent);

//PrintIfDebug(client," drop");


SDKCall(hSDKWeaponDrop, client, wpnent, false, false);
AcceptEntityInput(wpnent, "Kill");
//UTIL_Remove(wpnent);

}

}
else{
//PrintIfDebug(client,"no weapon");
//PrintToChatAll("no weapon");
}
// }
}
}
}
}

Here it is again with the code cleaned:

public Action:DeciSecondTimer(Handle:h,any:a)
{
timerskip--;
if(timerskip<1)
{
timerskip=10;
for(new client=1;client<=MaxClients;client++)
{
if(hasAnyRestriction[client]&&ValidPlayer(client,true))
{

new String:name[32];
GetClientName(client,name,sizeof(name));

new wpnent = GetCurrentWeaponEnt(client);


if(wpnent>0&&IsValidEdict(wpnent))
{
if(CheckCanUseWeapon(client,wpnent)){
//allow
}
else
{
SDKCall(hSDKWeaponDrop, client, wpnent, false, false);
AcceptEntityInput(wpnent, "Kill");
}

}
}
}
}
}
So here is the clusterfuck of wtf programing we have today. First part of the issue here is we have code that is designed to run on mutiple games which logically leads to errors. Sorry but it is best to use the best code for each game even if it takes more time. We already know that the code used above is not ideal for weapon removal. This is why we always try to remove the weapon before this code can activate b/c if it does it creates a glitch/crash. The ultimate solution would be to implement the correct weapon removal code here to correct the issue.

Next we have the issue of the timerskip--; part. Holy lazy fucking shit! So as we know this code runs every .1 seconds but you will see that this is here to make it so that it will skip 9 times and then run. So we get this:
0.0 seconds = run timerskip=10
0.1 seconds = skip timerskip=9
0.2 seconds = skip timerskip=8
0.3 seconds = skip timerskip=7
0.4 seconds = skip timerskip=6
0.5 seconds = skip timerskip=5
0.6 seconds = skip timerskip=4
0.7 seconds = skip timerskip=3
0.8 seconds = skip timerskip=2
0.9 seconds = skip timerskip=1
1.0 seconds = run timerskip=10

So how often does the program run? EVERY SECOND! So why they fuck not set the timer to 1 second. I will now tell you and I hope your sitting down. The programer decided this while working on the method but was too lazy to go back to the timer to change 0.1 to 1.0! YES that is the high qualtity programing we got here! Now I do not know who worked on this part of war3 if I remember correctly there was some other programers before Ownz took over everything b/c I doubt he would have done this as I know he is better than this.

So we will be fixing that shit.

Now onto order of fucking operations... yes we are reading from an array hasAnyRestriction[] beofre checking if the dam client we are checking for IS EVEN VALID while we are INSIDE OF A LOOP!!!!!!!

BUT IT GETS BETTER! We also have:


new String:name[32];
GetClientName(client,name,sizeof(name));

Which does, you guessed it NOTING. Not only is the string not being initilized as decl but it is totally worthless. WE ARE CREATING 32 slot arrays for every player in the server and storing their names in them every second for NO REASON. So that shit will be deleted!

One thing that is clear from reading over the sourcecode now that I actually know how to program. This shit is fucked up all over the pace. So here is the plan, after all the races get reprogramed I will then update to the latest war3 release. I will then go though every single line of all the war3 programes and reprogram every single one of them until 100% of all the code is fucking logicall and correct.

As I do not have any idea how to use the svn shit I will then just package my modified source and post it over on war3 for them to use to fix it for everyone. Hopefully they use it. If not at least our server will be really fucking stable.

ZERO
06-26-2012, 11:45 PM
Here it is at last! The pushto code that used to be used for things like moving spiderman this is taken from the python version:

def pushto(userid, coord, force):
if isinstance(coord, str):
coord = coord.split(',')

if hasattr(coord, '__iter__'):
if not isinstance(coord, Vector):
coord = Vector(coord)

if str(userid).startswith('#'):
userid = getUseridList(userid)

elif not hasattr(userid, '__iter__'):
userid = (userid, )

for user in userid:
if es.exists('userid', user):
loca = Vector(es.getplayerlocation(user))
coord -= loca
coord = coord * float(force)

es.setplayerprop(user, 'CBasePlayer.localdata.m_vecBaseVelocity', str(coord))

Here is our code for comparison:

new ult_level = War3_GetSkillLevel( client, thisRaceID, ULT_WEB );
new Float:startpos[3];
new Float:endpos[3];
new Float:localvector[3];
new Float:velocity[3];

GetClientAbsOrigin( client, startpos );
War3_GetAimEndPoint( client, endpos );

if(enemyImmunityNotInRange(client, endpos))
{
localvector[0] = endpos[0] - startpos[0];
localvector[1] = endpos[1] - startpos[1];
localvector[2] = endpos[2] - startpos[2];

velocity[0] = localvector[0] * PushForce[ult_level];
velocity[1] = localvector[1] * PushForce[ult_level];
velocity[2] = localvector[2] * PushForce[ult_level];

SetEntDataVector( client, m_vecBaseVelocity, velocity, true );

TE_SetupBeamPoints( startpos, endpos, BeamSprite, BeamSprite, 0, 0, 1.0, 1.0, 1.0, 0, 0.0, { 200, 200, 200, 255 }, 0 );
TE_SendToAll();
}
else
{
W3MsgEnemyHasImmunity(client);
}

You will notice that the code is exactly the same however I have a theory. The theory is that we actually need to multiply all forces by .25 to do the OB conversion. This is why spiderman and the others seem so much more powerful. As you see what we are doing here is EXACTLY the same as how long jump works exact that we also change the Z axis data. So if after the OB update we need to mult the pre ob force values by .25 then logically we need to do this for all force values that ever modify m_vecBaseVelocity. Races will be updated to take into account these changes.

acolyte_to_jippity
06-27-2012, 07:13 AM
you will notice that the code is exactly the same however i have a theory. The theory is that we actually need to multiply all forces by .25 to do the ob conversion. This is why spiderman and the others seem so much more powerful.


thank you!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!

+1

Assassin
06-27-2012, 04:36 PM
Holy hell that was a mess...yeah i think the beginning round timer should be re instituted so no bs like crypt scarabs the 1st second into a round. Also as to the shotgun part were you saying that they alrdy updated it? bc if not..it should be re instituted as well.

ZERO
06-27-2012, 05:14 PM
I think I undersand how that 10sec cvar actually works. I bet that all the races that have no cooldown on spawn in their code default to that and the ones that do have a cooldown on spawn in their code overrise this 10sec +freezetime value and use their own.

Therefore all races that currently do not have a cooldown on spawn need to have one added.

Maynard does this sound correct?

Blackmage
06-27-2012, 06:01 PM
For the XP loss for resetting skills, first, could we have a confirmation choice, so if we do the wrong command on the wcsmenu we don't lose XP for accidents?

Second, if we have it flat "next X kills" it's going to be more painful to lower leveled players than higher, since they get more XP per kill, on average. Perhaps something like "Next X kills, where X is your level". One problem I see no matter what you do, is going to be the storing of this information. If they switch race, you're either going to be letting them lose XP from another race, or have to store those variables somewhere. Dealing with crashes, disconnects, and just map changes, there is the ability of a lot of these things needing to be stored. Not sure if this will be enough to make a difference, but throwing this out there anyway.

maynard
06-27-2012, 06:06 PM
crpyt lord should be able to use it's ultimate as soon as the round starts as that's how it's always been on the sever. even back in the day before the major crash/update, it was able 2 use it the second the round starts, and granted it has like a 30 second cool down, randomly picks a target and hits them for only 25 damage, it's not really a big deal as the damage is low, and the target is random.

any race that can do it's ultimate right away should be left as is as it's always been that way, unless recently something glitches that I'm unaware of?... the races that can use their ultimate right away have ultimates that don't do direct target damage, or damage at all (vega, molecule etc.)

Suprise Butsexz
06-28-2012, 02:00 PM
So if the left hand glitch was due to bad coding of the restrictions on weapons or was from someone leaving and you taking there restrictions for a little anyway to do a check to make sure it the correct player before applying the restrictions so the only left hand glitch is faulty coding?

XX0wnsXY
06-28-2012, 11:39 PM
I agree with maynard and keeping the ultimates as they are with those that can use them right at the start. I can't think of one that poses a real problem. As Maynard said, Crypt lord has a high cool down and it's random so it's not much of an advantage.

Spasm
06-30-2012, 01:25 PM
Huge vagabond nerf. I think the base speed should be altered to compensate for the slow speed. The race is too slow, why change something thats been that way for years...

CYBER
06-30-2012, 01:54 PM
Huge vagabond nerf. I think the base speed should be altered to compensate for the slow speed. The race is too slow, why change something thats been that way for years...
this ^
vagabond needs to go back to what it was before the last nerf...
its not an op race, people have been trained to hunt vagabonds down and it shouldnt have that HUGE nerf...
it killed the race
specially that bash races are still out, and jack is fucking out too -.-

vaga should have an increased seem to balance this useless nerf that slowed it down WAYYY more than b efore the orange updates...
even before the updates, vaga has had the same speed and agility , specially for teleport, as just before the last nerf... nerfing it now would be going against the old ibis wcs standards for that race... a huge let down...

ZERO
09-24-2012, 02:38 PM
Dear god! I found the reason for the timer skip...

---------- Post added at 03:29 PM ---------- Previous post was at 03:27 PM ----------

You all may remember me complaing about this code:

The following method runs every .1 second to process weapon restrictions. Optimizations to this method may correct some bugs: (from War3Source_Engine_Weapon)

public Action:DeciSecondTimer(Handle:h,any:a){
timerskip--;
if(timerskip<1){
timerskip=10;
for(new client=1;client<=MaxClients;client++){
/*if(true){ //test
new wpnent = GetCurrentWeaponEnt(client);
if(FindSendPropOffs("CWeaponUSP","m_bSilencerOn")>0){

SetEntData(wpnent,FindSendPropOffs("CWeaponUSP","m_bSilencerOn"),true,true);
}

}*/

if(hasAnyRestriction[client]&&ValidPlayer(client,true)){

new String:name[32];
GetClientName(client,name,sizeof(name));
//PrintToChatAll("ValidPlayer %d",client);

new wpnent = GetCurrentWeaponEnt(client);
//PrintIfDebug(client," weapon ent %d %d",client,wpnent);
//new String:WeaponName[32];

//if(IsValidEdict(wpnent)){

// }

//PrintIfDebug(client," %s res: (%s) weapon: %s",name,weaponsAllowed[client],WeaponName);
// if(strlen(weaponsAllowed[client])>0){
if(wpnent>0&&IsValidEdict(wpnent)){


if (CheckCanUseWeapon(client,wpnent)){
//allow
}
else
{
//RemovePlayerItem(client,wpnent);

//PrintIfDebug(client," drop");


SDKCall(hSDKWeaponDrop, client, wpnent, false, false);
AcceptEntityInput(wpnent, "Kill");
//UTIL_Remove(wpnent);

}

}
else{
//PrintIfDebug(client,"no weapon");
//PrintToChatAll("no weapon");
}
// }
}
}
}
}

Here it is again with the code cleaned:

public Action:DeciSecondTimer(Handle:h,any:a)
{
timerskip--;
if(timerskip<1)
{
timerskip=10;
for(new client=1;client<=MaxClients;client++)
{
if(hasAnyRestriction[client]&&ValidPlayer(client,true))
{

new String:name[32];
GetClientName(client,name,sizeof(name));

new wpnent = GetCurrentWeaponEnt(client);


if(wpnent>0&&IsValidEdict(wpnent))
{
if(CheckCanUseWeapon(client,wpnent)){
//allow
}
else
{
SDKCall(hSDKWeaponDrop, client, wpnent, false, false);
AcceptEntityInput(wpnent, "Kill");
}

}
}
}
}
}
So here is the clusterfuck of wtf programing we have today. First part of the issue here is we have code that is designed to run on mutiple games which logically leads to errors. Sorry but it is best to use the best code for each game even if it takes more time. We already know that the code used above is not ideal for weapon removal. This is why we always try to remove the weapon before this code can activate b/c if it does it creates a glitch/crash. The ultimate solution would be to implement the correct weapon removal code here to correct the issue.

Next we have the issue of the timerskip--; part. Holy lazy fucking shit! So as we know this code runs every .1 seconds but you will see that this is here to make it so that it will skip 9 times and then run. So we get this:
0.0 seconds = run timerskip=10
0.1 seconds = skip timerskip=9
0.2 seconds = skip timerskip=8
0.3 seconds = skip timerskip=7
0.4 seconds = skip timerskip=6
0.5 seconds = skip timerskip=5
0.6 seconds = skip timerskip=4
0.7 seconds = skip timerskip=3
0.8 seconds = skip timerskip=2
0.9 seconds = skip timerskip=1
1.0 seconds = run timerskip=10

So how often does the program run? EVERY SECOND! So why they fuck not set the timer to 1 second. I will now tell you and I hope your sitting down. The programer decided this while working on the method but was too lazy to go back to the timer to change 0.1 to 1.0! YES that is the high qualtity programing we got here! Now I do not know who worked on this part of war3 if I remember correctly there was some other programers before Ownz took over everything b/c I doubt he would have done this as I know he is better than this.

So we will be fixing that shit.

Now onto order of fucking operations... yes we are reading from an array hasAnyRestriction[] beofre checking if the dam client we are checking for IS EVEN VALID while we are INSIDE OF A LOOP!!!!!!!

BUT IT GETS BETTER! We also have:


new String:name[32];
GetClientName(client,name,sizeof(name));

Which does, you guessed it NOTING. Not only is the string not being initilized as decl but it is totally worthless. WE ARE CREATING 32 slot arrays for every player in the server and storing their names in them every second for NO REASON. So that shit will be deleted!

One thing that is clear from reading over the sourcecode now that I actually know how to program. This shit is fucked up all over the pace. So here is the plan, after all the races get reprogramed I will then update to the latest war3 release. I will then go though every single line of all the war3 programes and reprogram every single one of them until 100% of all the code is fucking logicall and correct.

As I do not have any idea how to use the svn shit I will then just package my modified source and post it over on war3 for them to use to fix it for everyone. Hopefully they use it. If not at least our server will be really fucking stable.

---------- Post added at 03:38 PM ---------- Previous post was at 03:29 PM ----------

Today I was working to fix this program b/c it has caused issues with proper weapon removal since the hotfix I released the other day to fix some broken code due to a valve update.

I found the reason for the terrible idea and here is where it comes from. But first lets think about something I did not notice when I read that code the first time, timerskip is a GLOBAL variable and here is why:


CalculateWeaponRestCache(client){
new num=0;
new limit=War3_GetRacesLoaded();
new highestpri=0;
for(new raceid=0;raceid<=limit;raceid++){
restrictionEnabled[client][raceid]=(strlen(weaponsAllowed[client][raceid])>0)?true:false;
if(restrictionEnabled[client][raceid]){


num++;
if(restrictionPriority[client][raceid]>highestpri){
highestpri=restrictionPriority[client][raceid];
}
}
}
hasAnyRestriction[client]=num>0?true:false;


highestPriority[client]=highestpri;

timerskip=0; //force next timer to check weapons
}


timerskip=0; //force next timer to check weapons!!!!!!!!!111111111
REALLY NOW so that is how we call methods. This code ensures that the program checks and removes restricted weapons after the restriction is enabled rather than wait lets say 1 second. However the cause of this is to run a loop every .1 seconds instead of every 1 second for efficiency.

Below is the solution to this impossible problem:

public OnPluginStart()
{
CreateTimer(1.0,DeciSecondTimer,_,TIMER_REPEAT);


CalculateWeaponRestCache(client){
new num=0;
new limit=War3_GetRacesLoaded();
new highestpri=0;
for(new raceid=0;raceid<=limit;raceid++){
restrictionEnabled[client][raceid]=(strlen(weaponsAllowed[client][raceid])>0)?true:false;
if(restrictionEnabled[client][raceid]){


num++;
if(restrictionPriority[client][raceid]>highestpri){
highestpri=restrictionPriority[client][raceid];
}
}
}
hasAnyRestriction[client]=num>0?true:false;


highestPriority[client]=highestpri;

CheckRestrections(); //force to check weapons
}


public Action:DeciSecondTimer(Handle:h,any:a)
{
CheckRestrections();
}

public Action:CheckRestrections()
{
for(new client=1;client<=MaxClients;client++)
{
if(hasAnyRestriction[client]&&ValidPlayer(client,true))
{
new wpnent = GetCurrentWeaponEnt(client);

if(wpnent>0&&IsValidEdict(wpnent))
{
//Runs code below if weapon is blocked
if(!CheckCanUseWeapon(client,wpnent))
{
CS_DropWeapon(client, wpnent, false, false);
AcceptEntityInput(wpnent, "Kill");
}

}
}
}
}

Note obviously those are not actual final release code versions I just posted a lot more has been cleaned up after this post.

CYBER
09-24-2012, 08:38 PM
holy shit man, sounds like a headache :P

how long did it take u to find + process a fix ?

ZERO
09-24-2012, 10:19 PM
About 3min...

As soon as I saw that line I knew what was wrong and what I needed to do to fix it.