02-04-2014, 03:40 PM
Hello Zombie-Community.
I got many requests from modders and scripters, how the RotU mod works. In the following lines I will explain as short as possible how I made the mod working like that.
Everything is based on the Quake 3 Engine.
First of all I had to patch some .exe and .dll files to protect the server of being flooded or crashed (If you want the fixed files please feel free to contact me via PM or E-Mail).
The mod itself is based on kilometers of C++ codes. It took me quiet a long time to write about 15.000 lines of code.
Now how it is coded....
Every map has around 300 waypoints. Every waypoint is connected to all other waypoints in range. So I get a list of waypoints which looks like this:
To add those waypoints I wrote another "RotU-Developer-Tool" also based on automatically working methods (Just a Beta... I still add many waypoints by hand).
Now we got a list of around 300 waypoints.
Let's say we spawn a zombie on point A and we want him moving to point B behind a wall. The zombie has to calculate the shortest way to its destination around the wall while staying to the waypoints.
The method I used is named A*-Search.
This is a highly effective alrogithm that findes the shortest way to the destination waypoint.
Here is some code of the A*-Search method in my mod:
The method always returns the next waypoint the zombie should walk to. So if we repeat this method some times, the zombie will reach his destination at a time x. The time is calculated by DISTANCE/SPEED = TIME.
The rest of the mod is pretty simple coding.
For example setting up the waveorder:
Another aspect I got asked very often is how about saving the levels. How does this system work?
Well, all levels are sticked to your GUID (your CD key). But not only the levels. Everything is saved in a packet as a serverside variable.
For example this is my data packet (my GUID is replaced by *):
Another program running on my root machine saves the data packets to a mysql database.
So if the server restarts the datas are not lost.
This is made possible by the following code written in PHP (only a part of it):
To read the data on server side I used the following code to explode "-":
---------------------------------------------------------------------------------------------------
Of course there is much more behind the mod to make it working as it works now.
This was just an extrem short description where the mod is based on!
If you have further questions please feel free to ask in this topic.
---------------------------------------------------------------------------------------------------
If you want to buy the whole server side scripts (including levelsaver, serverfiles and developer-tool) please contact me via Mail or PM.
And always remember: I'm still doing my best to fix bugs and release new updates.
Buy Premium and get many new features in the next update package.
---------------------------------------------------------------------------------------------------
Regards,
Fabio
I got many requests from modders and scripters, how the RotU mod works. In the following lines I will explain as short as possible how I made the mod working like that.
Everything is based on the Quake 3 Engine.
First of all I had to patch some .exe and .dll files to protect the server of being flooded or crashed (If you want the fixed files please feel free to contact me via PM or E-Mail).
The mod itself is based on kilometers of C++ codes. It took me quiet a long time to write about 15.000 lines of code.
Now how it is coded....
Every map has around 300 waypoints. Every waypoint is connected to all other waypoints in range. So I get a list of waypoints which looks like this:
Code:
main()
{
level.waypoints = [];
level.waypoints[0] = spawnstruct();
level.waypoints[0].origin = (-10155.5,-8417.45,0.124996);
level.waypoints[0].childCount = 2;
level.waypoints[0].children[0] = 1;
level.waypoints[0].children[1] = 39;
level.waypoints[1] = spawnstruct();
level.waypoints[1].origin = (-10196.9,-8574.94,0.124996);
level.waypoints[1].childCount = 2;
level.waypoints[1].children[0] = 2;
level.waypoints[1].children[1] = 0;
level.waypoints[2] = spawnstruct();
level.waypoints[2].origin = (-10384.7,-8622.07,0.124996);
level.waypoints[2].childCount = 2;
level.waypoints[2].children[0] = 3;
level.waypoints[2].children[1] = 1;
level.waypoints[3] = spawnstruct();
level.waypoints[3].origin = (-10620.7,-8626.96,0.124996);
level.waypoints[3].childCount = 2;
level.waypoints[3].children[0] = 4;
level.waypoints[3].children[1] = 2;
level.waypoints[4] = spawnstruct();
level.waypoints[4].origin = (-10798.3,-8591.58,0.124996);
level.waypoints[4].childCount = 2;
level.waypoints[4].children[0] = 5;
level.waypoints[4].children[1] = 3;
level.waypoints[5] = spawnstruct();
level.waypoints[5].origin = (-11024.3,-8618.33,0.124996);
level.waypoints[5].childCount = 2;
level.waypoints[5].children[0] = 6;
level.waypoints[5].children[1] = 4;
.
.
.
}
To add those waypoints I wrote another "RotU-Developer-Tool" also based on automatically working methods (Just a Beta... I still add many waypoints by hand).
Now we got a list of around 300 waypoints.
Let's say we spawn a zombie on point A and we want him moving to point B behind a wall. The zombie has to calculate the shortest way to its destination around the wall while staying to the waypoints.
The method I used is named A*-Search.
This is a highly effective alrogithm that findes the shortest way to the destination waypoint.
Here is some code of the A*-Search method in my mod:
Code:
AStarSearch(startWp, goalWp)
{
self endon("player_killed");
pQOpen = [];
pQSize = 0;
closedList = [];
listSize = 0;
s = spawnstruct();
s.g = 0; //start node
s.h = distance(level.waypoints[startWp].origin, level.waypoints[goalWp].origin);
s.f = s.g + s.h;
s.wpIdx = startWp;
s.parent = spawnstruct();
s.parent.wpIdx = -1;
pQOpen[pQSize] = spawnstruct();
pQOpen[pQSize] = s; //push s on Open
pQSize++;
while(!PQIsEmpty(pQOpen, pQSize))
{
//wait 0.01; //todo
n = pQOpen[0];
highestPriority = 9999999999;
bestNode = -1;
for(i = 0; i < pQSize; i++)
{
if(pQOpen[i].f < highestPriority)
{
bestNode = i;
highestPriority = pQOpen[i].f;
}
}
if(bestNode != -1)
{
n = pQOpen[bestNode];
//remove node from queue
for(i = bestNode; i < pQSize-1; i++)
{
pQOpen[i] = pQOpen[i+1];
}
pQSize--;
}
else
{
return;
}
//if n is a goal node; construct path, return success
if(n.wpIdx == goalWp)
{
x = n;
for(z = 0; z < 1000; z++)
{
parent = x.parent;
if(parent.parent.wpIdx == -1)
{
return x.wpIdx;
}
x = parent;
}
return;
}
.
.
.
.
.
.
.
.
}
}
The method always returns the next waypoint the zombie should walk to. So if we repeat this method some times, the zombie will reach his destination at a time x. The time is calculated by DISTANCE/SPEED = TIME.
The rest of the mod is pretty simple coding.
For example setting up the waveorder:
Code:
setupwaves()
{
level.wave_type = [];
level.wave_type[0] = "normal";
////// wavetypes here //////
//normal, toxic, freeze, speed, burning, chaos, boss1, boss3, endboss
level.wave_type[1] = "normal";
level.wave_type[2] = "toxic";
level.wave_type[3] = "normal";
level.wave_type[4] = "speed";
level.wave_type[5] = "pseudo";
level.wave_type[6] = "mixed";
level.wave_type[7] = "normal";
level.wave_type[8] = "freeze";
level.wave_type[9] = "burning";
level.wave_type[10] = "pseudo";
level.wave_type[11] = "normal";
level.wave_type[12] = "chaos";
level.wave_type[13] = "normal";
level.wave_type[14] = "mixed";
level.wave_type[15] = "pseudo";
level.wave_type[16] = "boss1";
level.wave_type[17] = "freeze";
level.wave_type[18] = "chaos";
level.wave_type[19] = "pseudo";
level.wave_type[20] = "boss3";
level.wave_type[21] = "normal";
level.wave_type[22] = "mixed";
level.wave_type[23] = "endboss";
level.maxwaves = 23;
//////////////////////////////
}
Another aspect I got asked very often is how about saving the levels. How does this system work?
Well, all levels are sticked to your GUID (your CD key). But not only the levels. Everything is saved in a packet as a serverside variable.
For example this is my data packet (my GUID is replaced by *):
Code:
set data_****** 200-51264650-35-27-35-35-0-0-179-1-0-6910-0-181-0-90-0-0-0-6910-0-4-1-35-35-1
Another program running on my root machine saves the data packets to a mysql database.
So if the server restarts the datas are not lost.
This is made possible by the following code written in PHP (only a part of it):
Code:
.
.
.
$result = $con->rcon($ip, $port, $password, "cvarlist data_");
$pattern = '|^[A-Z ]{7} (\w+) "(.*)"$|i';
foreach(array_map("rtrim", explode("\n", $result)) as $value)
{
if(preg_match($pattern, $value, $subpatterns))
{
$data = $subpatterns[2]."-".preg_replace("/data_/", "", $subpatterns[1]);
$cvars[strtolower($subpatterns[1])] = explode("-", $data);
}
}
.
.
.
To read the data on server side I used the following code to explode "-":
Code:
parms = explode(var, "-");
self.rotu_level = (int)parms[0];
self.rotu_points = (int)parms[1];
self.skill_armored = (int)parms[2];
self.skill_soldier = (int)parms[3];
self.skill_engineer = (int)parms[4];
self.skill_medic = (int)parms[5];
self.skillpoints_available = (int)parms[6];
.
.
.
.
---------------------------------------------------------------------------------------------------
Of course there is much more behind the mod to make it working as it works now.
This was just an extrem short description where the mod is based on!
If you have further questions please feel free to ask in this topic.
---------------------------------------------------------------------------------------------------
If you want to buy the whole server side scripts (including levelsaver, serverfiles and developer-tool) please contact me via Mail or PM.
And always remember: I'm still doing my best to fix bugs and release new updates.
Buy Premium and get many new features in the next update package.
---------------------------------------------------------------------------------------------------
Regards,
Fabio