Using this?Can libcod enforce it before player connects?Code:player setClientCvar("cl_allowdownload", "1");
Printable View
Using this?Can libcod enforce it before player connects?Code:player setClientCvar("cl_allowdownload", "1");
Ok thanks. I'll give it a try when i install libcod.
I need a little help.
Saving the players stats and updating them works fine using the functions from _stattracking.gsc (the non mysql version). Now i am trying to add a hud for displaying them. So because my coding experience is limited i tried modifying _hud_playerscore.gsc to test. I made a file called _myhud.gsc that contains :
I tried calling _myhud.gsc within _stattracking.gsc in the init function.Code:init()
{
level thread onPlayerConnect();
}
onPlayerConnect()
{
for(;;)
{
level waittill("connecting", player);
player thread onPlayerSpawned();
player thread onJoinedTeam();
player thread onJoinedSpectators();
player thread onUpdatePlayerScoreHUD();
}
}
onJoinedTeam()
{
self endon("disconnect");
for(;;)
{
self waittill("joined_team");
self thread removePlayerHUD();
}
}
onJoinedSpectators()
{
self endon("disconnect");
for(;;)
{
self waittill("joined_spectators");
self thread removePlayerHUD();
}
}
onPlayerSpawned()
{
self endon("disconnect");
for(;;)
{
self waittill("spawned_player");
if(!isdefined(self.hud_deaths))
{
self.hud_deaths = newClientHudElem(self);
self.hud_deaths.horzAlign = "left";
self.hud_deaths.vertAlign = "top";
self.hud_deaths.x = 36;
self.hud_deaths.y = 46;
self.hud_deaths.font = "default";
self.hud_deaths.fontscale = 2;
self.hud_deaths.archived = false;
}
self thread updatePlayerScoreHUD();
}
}
onUpdatePlayerScoreHUD()
{
for(;;)
{
self waittill("update_playerscore_hud");
self thread updatePlayerScoreHUD();
}
}
updatePlayerScoreHUD()
{
if(isDefined(self.hud_deaths))
deaths = self getstat("deaths");
self.hud_deaths setValue(deaths);
}
removePlayerHUD()
{
if(isDefined(self.hud_deaths))
self.hud_deaths destroy();
}
When i try to run server i get this error:Code:init()
{
game["menu_clientcmd"] = "clientcmd";
precacheMenu(game["menu_clientcmd"]);
init_stattracking();
init_ranks();
thread waitforconnect();
thread scanForBan();
thread maps\mp\gametypes\_myhud::init();
}
Any help would be highly appreciatedCode:******* script compile error *******
uninitialised variable 'deaths': (file 'maps/mp/gametypes/_myhud.gsc', line 86)
self.hud_deaths setValue(deaths);
*
************************************
********************
ERROR: script compile error
(see console for details)
********************
----- Server Shutdown -----
Sending heartbeat to cod2master.activision.com
==== ShutdownGame ====
Change
toCode:updatePlayerScoreHUD()
{
if(isDefined(self.hud_deaths))
deaths = self getstat("deaths");
self.hud_deaths setValue(deaths);
}
Code:updatePlayerScoreHUD()
{
if(isDefined(self.hud_deaths))
{
deaths = self getstat("deaths");
self.hud_deaths setValue(deaths);
}
}
Ok that was too obvious for me to see :)
I also had to add #include maps\mp\gametypes\_stattracking; in _myhud.gsc and rename init() to init1()
Now it loads fine without error but allways displays zero.
Do i need to rename the functions in _myhud.gsc ? They have the same name as in _hud_playerscore.gsc. Does it cause any conflict if i don't?
Edit:
Forgot to tell that i tested it local on my pc playing alone and throwing grenades to my self. If it means anything.
Ok i managed to fix it. Was some dumb declaration i made (for debugging perposes) in spawnPlayer() function. Now it displays correctly.
Ok so i made a basic hud for displaying some of the player stats i use. It's probably not the most efficient one (especially the part with the rank names) but i want to share it anyways. Suggestions and corrections are welcome.
Code:#include maps\mp\gametypes\_stattracking;
init1()
{
game["deaths"] = &"^6Total Deaths: ^7";
game["kills"] = &"^3Total kills: ^7";
game["headshots"] = &"^3Headshots: ^7";
game["suicides"] = &"^6Suicides: ^7";
game["rank"] = &"^8Rank: ^5";
game["killstreak"] = &"^3Longest Killstreak: ^7";
game["melee"] = &"^3Melee kills: ^7";
game["teamkills"] = &"^6Team kills: ^7";
precacheShader("white");
precacheString(game["deaths"]);
precacheString(game["kills"]);
precacheString(game["headshots"]);
precacheString(game["melee"]);
precacheString(game["suicides"]);
precacheString(game["rank"]);
precacheString(game["killstreak"]);
precacheString(game["teamkills"]);
level thread onPlayerConnect();
level thread ranknamesinit();
}
onPlayerConnect()
{
for(;;)
{
level waittill("connecting", player);
player thread onPlayerSpawned();
player thread onJoinedTeam();
player thread onJoinedSpectators();
player thread onUpdatePlayerScoreHUD();
}
}
onJoinedTeam()
{
self endon("disconnect");
for(;;)
{
self waittill("joined_team");
self thread removePlayerHUD();
}
}
onJoinedSpectators()
{
self endon("disconnect");
for(;;)
{
self waittill("joined_spectators");
self thread removePlayerHUD();
}
}
onPlayerSpawned()
{
self endon("disconnect");
offset=0;
gametype = getCvar("g_gametype");
frf="0";
frf= getCvar("scr_friendlyfire");
if(gametype == "tdm")
offset=25;
for(;;)
{
self waittill("spawned_player");
if(!isdefined(self.hud_kills))
{
self.hud_kills = newClientHudElem(self);
self.hud_kills.horzAlign = "left";
self.hud_kills.vertAlign = "top";
self.hud_kills.x = 10;
self.hud_kills.y = 50 + offset;
self.hud_kills.font = "default";
self.hud_kills.fontscale = .8;
self.hud_kills.archived = false;
self.hud_kills.label = game["kills"];
}
if(!isdefined(self.hud_deaths))
{
self.hud_deaths = newClientHudElem(self);
self.hud_deaths.horzAlign = "left";
self.hud_deaths.vertAlign = "top";
self.hud_deaths.x = 10;
self.hud_deaths.y = 58 + offset;
self.hud_deaths.font = "default";
self.hud_deaths.fontscale = .8;
self.hud_deaths.archived = false;
self.hud_deaths.label = game["deaths"];
}
if(!isdefined(self.hud_suicides))
{
self.hud_suicides = newClientHudElem(self);
self.hud_suicides.horzAlign = "left";
self.hud_suicides.vertAlign = "top";
self.hud_suicides.x = 10;
self.hud_suicides.y = 66 + offset;
self.hud_suicides.font = "default";
self.hud_suicides.fontscale = .8;
self.hud_suicides.archived = false;
self.hud_suicides.label = game["suicides"];
}
if(!isdefined(self.hud_headshots))
{
self.hud_headshots = newClientHudElem(self);
self.hud_headshots.horzAlign = "left";
self.hud_headshots.vertAlign = "top";
self.hud_headshots.x = 10;
self.hud_headshots.y = 74 + offset;
self.hud_headshots.font = "default";
self.hud_headshots.fontscale = .8;
self.hud_headshots.archived = false;
self.hud_headshots.label = game["headshots"];
}
if(!isdefined(self.hud_melee))
{
self.hud_melee = newClientHudElem(self);
self.hud_melee.horzAlign = "left";
self.hud_melee.vertAlign = "top";
self.hud_melee.x = 10;
self.hud_melee.y = 82 + offset;
self.hud_melee.font = "default";
self.hud_melee.fontscale = .8;
self.hud_melee.archived = false;
self.hud_melee.label = game["melee"];
}
if(!isdefined(self.hud_lkillstr))
{
self.hud_lkillstr = newClientHudElem(self);
self.hud_lkillstr.horzAlign = "left";
self.hud_lkillstr.vertAlign = "top";
self.hud_lkillstr.x = 10;
self.hud_lkillstr.y = 90 + offset;
self.hud_lkillstr.font = "default";
self.hud_lkillstr.fontscale = .8;
self.hud_lkillstr.archived = false;
self.hud_lkillstr.label = game["killstreak"];
}
if(!isdefined(self.hud_rank))
{
self.hud_rank = newClientHudElem(self);
self.hud_rank.horzAlign = "left";
self.hud_rank.vertAlign = "top";
self.hud_rank.x = 10;
self.hud_rank.y = 98 + offset;
self.hud_rank.font = "default";
self.hud_rank.fontscale = .8;
self.hud_rank.archived = false;
self.hud_rank.label = game["rank"];
}
if(!isdefined(self.hud_teamkills) && gametype=="tdm" && frf=="1")
{
self.hud_teamkills = newClientHudElem(self);
self.hud_teamkills.horzAlign = "left";
self.hud_teamkills.vertAlign = "top";
self.hud_teamkills.x = 10;
self.hud_teamkills.y = 106 + offset;
self.hud_teamkills.font = "default";
self.hud_teamkills.fontscale = .8;
self.hud_teamkills.archived = false;
self.hud_teamkills.label = game["teamkills"];
}
self thread updatePlayerScoreHUD();
}
}
onUpdatePlayerScoreHUD()
{
for(;;)
{
self waittill("update_playerscore_hud");
self thread updatePlayerScoreHUD();
}
}
updatePlayerScoreHUD()
{
if(isDefined(self.hud_deaths))
{
deaths = self getstat("deaths");
self.hud_deaths setValue(deaths);
}
if(isDefined(self.hud_headshots))
{
headshots = self getstat("headshots");
self.hud_headshots setValue(headshots);
}
if(isDefined(self.hud_kills))
{
kills= self getstat("kills");
self.hud_kills setValue(kills);
}
if(isdefined(self.hud_suicides))
{
suicides= self getstat("suicides");
self.hud_suicides setValue(suicides);
}
if(isdefined(self.hud_melee))
{
melee= self getstat("meleekills");
self.hud_melee setValue(melee);
}
if(isdefined(self.hud_lkillstr))
{
lkillstr= self getstat("longest_killstreak");
self.hud_lkillstr setValue(lkillstr);
}
if(isdefined(self.hud_rank))
{
rank= self getstat("rank");
self getrankname(rank);
}
if(isdefined(self.hud_teamkills))
{
teamkills= self getstat("teamkills");
self.hud_teamkills setValue(teamkills);
}
}
removePlayerHUD()
{
if(isDefined(self.hud_deaths))
self.hud_deaths destroy();
if(isDefined(self.hud_headshots))
self.hud_headshots destroy();
if(isDefined(self.hud_kills))
self.hud_kills destroy();
if(isdefined(self.hud_suicides))
self.hud_suicides destroy();
if(isdefined(self.hud_melee))
self.hud_melee destroy();
if(isdefined(self.hud_lkillstr))
self.hud_lkillstr destroy();
if(isdefined(self.hud_rank))
self.hud_rank destroy();
if(isdefined(self.hud_teamkills))
self.hud_teamkills destroy();
}
getrankname(rank)
{
switch(rank)
{
case 0:
self.hud_rank setText(game["0"]);
break;
case 1:
self.hud_rank setText(game["1"]);
break;
case 2:
self.hud_rank setText(game["2"]);
break;
case 3:
self.hud_rank setText(game["3"]);
break;
case 4:
self.hud_rank setText(game["4"]);
break;
case 5:
self.hud_rank setText(game["5"]);
break;
case 6:
self.hud_rank setText(game["6"]);
break;
case 7:
self.hud_rank setText(game["7"]);
break;
case 8:
self.hud_rank setText(game["8"]);
break;
case 9:
self.hud_rank setText(game["9"]);
break;
case 10:
self.hud_rank setText(game["10"]);
break;
case 11:
self.hud_rank setText(game["11"]);
break;
case 12:
self.hud_rank setText(game["12"]);
break;
case 13:
self.hud_rank setText(game["13"]);
break;
case 14:
self.hud_rank setText(game["14"]);
break;
case 15:
self.hud_rank setText(game["15"]);
break;
case 16:
self.hud_rank setText(game["16"]);
break;
case 17:
self.hud_rank setText(game["17"]);
break;
case 18:
self.hud_rank setText(game["18"]);
break;
case 19:
self.hud_rank setText(game["19"]);
break;
case 20:
self.hud_rank setText(game["20"]);
break;
case 21:
self.hud_rank setText(game["21"]);
break;
case 22:
self.hud_rank setText(game["22"]);
break;
case 23:
self.hud_rank setText(game["23"]);
break;
case 24:
self.hud_rank setText(game["24"]);
break;
case 25:
self.hud_rank setText(game["25"]);
break;
case 26:
self.hud_rank setText(game["26"]);
break;
case 27:
self.hud_rank setText(game["27"]);
break;
case 28:
self.hud_rank setText(game["28"]);
break;
case 29:
self.hud_rank setText(game["29"]);
break;
case 30:
self.hud_rank setText(game["30"]);
break;
case 31:
self.hud_rank setText(game["31"]);
break;
case 32:
self.hud_rank setText(game["32"]);
break;
case 33:
self.hud_rank setText(game["33"]);
break;
case 34:
self.hud_rank setText(game["34"]);
break;
case 35:
self.hud_rank setText(game["35"]);
break;
case 36:
self.hud_rank setText(game["36"]);
break;
case 37:
self.hud_rank setText(game["37"]);
break;
case 38:
self.hud_rank setText(game["38"]);
break;
case 39:
self.hud_rank setText(game["39"]);
break;
case 40:
self.hud_rank setText(game["40"]);
break;
case 41:
self.hud_rank setText(game["41"]);
break;
case 42:
self.hud_rank setText(game["42"]);
break;
case 43:
self.hud_rank setText(game["43"]);
break;
case 44:
self.hud_rank setText(game["44"]);
break;
case 45:
self.hud_rank setText(game["45"]);
break;
case 46:
self.hud_rank setText(game["46"]);
break;
case 47:
self.hud_rank setText(game["47"]);
break;
case 48:
self.hud_rank setText(game["48"]);
break;
case 49:
self.hud_rank setText(game["49"]);
break;
case 50:
self.hud_rank setText(game["50"]);
break;
case 51:
self.hud_rank setText(game["51"]);
break;
case 52:
self.hud_rank setText(game["52"]);
break;
case 53:
self.hud_rank setText(game["53"]);
break;
case 54:
self.hud_rank setText(game["54"]);
break;
}
}
ranknamesinit()
{
game["0"] = &"Private First Class";
game["1"] = &"Private First Class I";
game["2"] = &"Private First Class II";
game["3"] = &"Lance Corporal";
game["4"] = &"Lance Corporal I";
game["5"] = &"Lance Corporal II";
game["6"] = &"Corporal";
game["7"] = &"Corporal I";
game["8"] = &"Corporal II";
game["9"] = &"Sergeant";
game["10"] = &"Sergeant I";
game["11"] = &"Sergeant II";
game["12"] = &"Staff Sergeant";
game["13"] = &"Staff Sergeant I";
game["14"] = &"Staff Sergeant II";
game["15"] = &"Gunnery Sergeant";
game["16"] = &"Gunnery Sergeant I";
game["17"] = &"Gunnery Sergeant II";
game["18"] = &"Master Sergeant";
game["19"] = &"Master Sergeant I";
game["20"] = &"Master Sergeant II";
game["21"] = &"Master Gunnery Sergeant";
game["22"] = &"Master Gunnery Sergeant I";
game["23"] = &"Master Gunnery Sergeant II";
game["24"] = &"2nd Lieutenant";
game["25"] = &"2nd Lieutenant I";
game["26"] = &"2nd Lieutenant II";
game["27"] = &"1st Lieutenant";
game["28"] = &"1st Lieutenant I";
game["29"] = &"1st Lieutenant II";
game["30"] = &"Captain";
game["31"] = &"Captain I";
game["32"] = &"Captain II";
game["33"] = &"Major";
game["34"] = &"Major I";
game["35"] = &"Major II";
game["36"] = &"Lt. Colonel";
game["37"] = &"Lt. Colonel I";
game["38"] = &"Lt. Colonel II";
game["39"] = &"Colonel";
game["40"] = &"Colonel I";
game["41"] = &"Colonel II";
game["42"] = &"Brigadier General";
game["43"] = &"Brigadier General I";
game["44"] = &"Brigadier General II";
game["45"] = &"Major General";
game["46"] = &"Major General I";
game["47"] = &"Major General II";
game["48"] = &"Lieutenant General";
game["49"] = &"Lieutenant General I";
game["50"] = &"Lieutenant General II";
game["51"] = &"General";
game["52"] = &"General I";
game["53"] = &"General II";
game["54"] = &"Commander";
precacheString(game["0"]);
precacheString(game["1"]);
precacheString(game["2"]);
precacheString(game["3"]);
precacheString(game["4"]);
precacheString(game["5"]);
precacheString(game["6"]);
precacheString(game["7"]);
precacheString(game["8"]);
precacheString(game["9"]);
precacheString(game["10"]);
precacheString(game["11"]);
precacheString(game["12"]);
precacheString(game["13"]);
precacheString(game["14"]);
precacheString(game["15"]);
precacheString(game["16"]);
precacheString(game["17"]);
precacheString(game["18"]);
precacheString(game["19"]);
precacheString(game["20"]);
precacheString(game["21"]);
precacheString(game["22"]);
precacheString(game["23"]);
precacheString(game["24"]);
precacheString(game["25"]);
precacheString(game["26"]);
precacheString(game["27"]);
precacheString(game["28"]);
precacheString(game["29"]);
precacheString(game["30"]);
precacheString(game["31"]);
precacheString(game["32"]);
precacheString(game["33"]);
precacheString(game["34"]);
precacheString(game["35"]);
precacheString(game["36"]);
precacheString(game["37"]);
precacheString(game["38"]);
precacheString(game["39"]);
precacheString(game["40"]);
precacheString(game["41"]);
precacheString(game["42"]);
precacheString(game["43"]);
precacheString(game["44"]);
precacheString(game["45"]);
precacheString(game["46"]);
precacheString(game["47"]);
precacheString(game["48"]);
precacheString(game["49"]);
precacheString(game["50"]);
precacheString(game["51"]);
precacheString(game["52"]);
precacheString(game["53"]);
precacheString(game["54"]);
}
PHP Code:
getrankname(rank)
{
if(rank >= 0 && rank < game["rankname"].size)
self.hud_rank setText(game["rankname"][rank]);
}
ranknamesinit()
{
game["rankname"] = [];
game["rankname"][0] = &"Private First Class";
game["rankname"][1] = &"Private First Class I";
game["rankname"][2] = &"Private First Class II";
game["rankname"][3] = &"Lance Corporal";
game["rankname"][4] = &"Lance Corporal I";
game["rankname"][5] = &"Lance Corporal II";
game["rankname"][6] = &"Corporal";
game["rankname"][7] = &"Corporal I";
game["rankname"][8] = &"Corporal II";
game["rankname"][9] = &"Sergeant";
game["rankname"][10] = &"Sergeant I";
game["rankname"][11] = &"Sergeant II";
game["rankname"][12] = &"Staff Sergeant";
game["rankname"][13] = &"Staff Sergeant I";
game["rankname"][14] = &"Staff Sergeant II";
game["rankname"][15] = &"Gunnery Sergeant";
game["rankname"][16] = &"Gunnery Sergeant I";
game["rankname"][17] = &"Gunnery Sergeant II";
game["rankname"][18] = &"Master Sergeant";
game["rankname"][19] = &"Master Sergeant I";
game["rankname"][20] = &"Master Sergeant II";
game["rankname"][21] = &"Master Gunnery Sergeant";
game["rankname"][22] = &"Master Gunnery Sergeant I";
game["rankname"][23] = &"Master Gunnery Sergeant II";
game["rankname"][24] = &"2nd Lieutenant";
game["rankname"][25] = &"2nd Lieutenant I";
game["rankname"][26] = &"2nd Lieutenant II";
game["rankname"][27] = &"1st Lieutenant";
game["rankname"][28] = &"1st Lieutenant I";
game["rankname"][29] = &"1st Lieutenant II";
game["rankname"][30] = &"Captain";
game["rankname"][31] = &"Captain I";
game["rankname"][32] = &"Captain II";
game["rankname"][33] = &"Major";
game["rankname"][34] = &"Major I";
game["rankname"][35] = &"Major II";
game["rankname"][36] = &"Lt. Colonel";
game["rankname"][37] = &"Lt. Colonel I";
game["rankname"][38] = &"Lt. Colonel II";
game["rankname"][39] = &"Colonel";
game["rankname"][40] = &"Colonel I";
game["rankname"][41] = &"Colonel II";
game["rankname"][42] = &"Brigadier General";
game["rankname"][43] = &"Brigadier General I";
game["rankname"][44] = &"Brigadier General II";
game["rankname"][45] = &"Major General";
game["rankname"][46] = &"Major General I";
game["rankname"][47] = &"Major General II";
game["rankname"][48] = &"Lieutenant General";
game["rankname"][49] = &"Lieutenant General I";
game["rankname"][50] = &"Lieutenant General II";
game["rankname"][51] = &"General";
game["rankname"][52] = &"General I";
game["rankname"][53] = &"General II";
game["rankname"][54] = &"Commander";
for(i = 0; i < game["rankname"].size; i++)
precachestring(game["rankname"][i]);
}
Thank you for the correction. I will try it as soon as possible.
If i modify the getstat() function like this it returns the rank name instead of the rank number. Is there a way to put the result in an array to use in the hud? Because i tried and it gave me error about not being localized string. Sorry for asking too many questions...
Code:getstat(stat)
{
switch(stat)
{
case "rank":
return level.ranks[self.stats["rank"]].name;
}
if(!isdefined(stat))
return;
if(!isdefined(self) || !isplayer(self))
return;
if(!isdefined(self.stats[stat]))
return 0;
else
return self.stats[stat];
}
Just use the above stuff.
Hi i need a little of your expertise again.
I decided to use libcod to get mysql function. I used this version https://github.com/voron00/libcod. I set up the database and create the table. Along with the "login, playername, challenge, response" colums i added some more to store the player stats. So far so good. I modified the createnewaccount() function to fil up the rest of the columns and it works ok i think. Also I modified the updatestats() as shown below and it also seem to work ok. The only thing i cannot get to work is to load the values back to self.stats array. The loadtstats() function i got is shown below. Please point me in the right direction.
Code:createnewaccount()
{
created = false;
str = "";
chl = "";
chl_resp = "";
while(!created)
{
str = "";
src = "abcdefghijklmnopqrstuvwxyz0123456789";
chl = "Challenge_";
chl_resp = "";
for(i = 0; i < 30; i++)
{
str += src[randomint(src.size)];
chl += src[randomint(src.size)];
chl_resp += src[randomint(src.size)];
}
self.izno["login_challenge"] = chl;
self.izno["login_response"] = chl_resp;
result = [[level.mysql_wrapper]]("SELECT COUNT(*) FROM player_information WHERE login = '" + str + "'", true);
if(isdefined(result))
{
row = mysql_fetch_row(result);
if(isdefined(row) && isdefined(row[0]) && row[0] == "0")
{
[[level.mysql_wrapper]]("INSERT IGNORE INTO player_information (login, playername, challenge, response) VALUES ('" + str + "', '" + maps\mp\gametypes\_mysql::stripstring(self.name) + "', '" + chl + "', '" + chl_resp + "')", false);
for(i=0;i<level.stats.size;i++)
{
[[level.mysql_wrapper]]("UPDATE player_information set " + level.stats[i] +"= 0 WHERE login = '" + str + "'",false);
}
created = true;
}
mysql_free_result(result);
}
}
self.izno["login"] = str;
self thread monitorsave(str, chl, chl_resp);
}
Code:updatestats()
{
result = [[level.mysql_wrapper]]("SELECT COUNT(*) FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
{
for(i=0;i<level.stats.size;i++)
{
[[level.mysql_wrapper]]("UPDATE player_information set " + level.stats[i] +"="+self.stats[level.stats[i]]+" WHERE login = '" + self.izno["login"] + "'",false);
}
}
mysql_free_result(result);
}
self notify("update_playerhud_score");
self maps\mp\gametypes\_myhud::updatePlayerScoreHUD();
}
Code:loadstats()
{
result = [[level.mysql_wrapper]]("SELECT COUNT(*) FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
{
for(i=0;i<level.stats.size;i++)
{
self.stats[i]=[[level.mysql_wrapper]]("Select "+self.stats[level.stats[i]]+" from player_information WHERE login = '" + self.izno["login"] + "'",true);
}
}
mysql_free_result(result);
}
self checkrank();
self thread counter();
self thread checkban();
}
After some more research i figured out that i need a function in the database. Something like this.
But i can not get it to work properly.
When i try executing it in MYSQL Workbench it gives me "Error Code: 1366. Incorrect integer value: 'kills' for column 'ret' at row 1".Code:CREATE FUNCTION `return_value`(login_ char(30), stat_ char(10)) RETURNS int(11)
BEGIN
declare ret int(11);
set ret = null;
select stat_ from cod2stats.player_information where login = login_ into ret;
RETURN ret;
END
But if i change it to "select kills from cod2stats.player_information where login = login_ into ret;" it returns the correct value. Any suggestions?
You're not properly retrieving the stuff from the database. You're storing the "result" pointer (!) in the self.stats array, which is a seemingly random number. Instead use the result to fetch_row.
Omg i am so noob... Thank you very much
I managed to retrieve the stats from the database using this function.
Code:loadstats()
{
result = [[level.mysql_wrapper]]("SELECT * FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
row = mysql_fetch_row(result);
if(isdefined(row) )
{
for(i=0;i<level.stats.size;i++)
{
self.stats[level.stats[i]] = int(row[i+4]);
}
}
mysql_free_result(result);
}
self checkrank();
self thread counter();
self thread checkban();
}
I tested the mysql functions on my server. Although it loads and saves the data fine and showing properly on the custom hud it really starts to lag the game if there are more than 10 players.
The main suspect is this function. I know it is not optimized because it write all the player stats every time it is called.
It is called several times by every player like on every kill ,death etc. So one solution to make it more efficient would be to make it update one stat at a time and call it like updatestats(stat). I don't know if it would make a big difference so i decided to use asyncronous mysql queries since they are better.Code:updatestats()
{
result = [[level.mysql_wrapper]]("SELECT * FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
row = mysql_fetch_row(result);
if(isdefined(row))
{
for(i=0;i<level.stats.size;i++)
{
[[level.mysql_wrapper]]("UPDATE player_information set " + level.stats[i] +" = "+self.stats[level.stats[i]]+" WHERE login = '" + self.izno["login"] + "'",false);
}
[[level.mysql_wrapper]]("UPDATE player_information set playername = '"+self.name+"' WHERE login = '" + self.izno["login"] + "'",false);
}
mysql_free_result(result);
}
self notify("update_playerhud_score");
self maps\mp\gametypes\_myhud::updatePlayerScoreHUD();
}
I started reading this thread https://killtube.org/showthread.php?...ll=1#post13719 but i got more confused.
How is it supposed to be called in my situation? Any help please??Code:asyncQuery(query, function, args)
{
id = mysql_async_createQuery(query);
task = spawnstruct();
task.query = query;
task.invoker = self;
task.function = function;
task.args = args;
level.JH_mysqlAsync["" + id] = task;
}
After some trial and error i came up with this:
If i try to use mysql_async_getresult_and_free(async_id); I get this error. If i don't use it it stores the data and does not give any error. Is it ok like this? Does it need anything else? I plan to make it more efficient by specifing the stat i need to update. But for now i first want to get it to work properly.Code:updatestats()
{
async_id = maps\mp\gametypes\_mysql::asyncQuery("SELECT * FROM player_information WHERE login = '" + self.izno["login"] + "'",::actualupdate );
//mysql_async_getresult_and_free(async_id);
}
actualupdate(rows,args)
{
if(isDefined(rows))
{
for(i=0;i<level.stats.size;i++)
{
async_id = maps\mp\gametypes\_mysql::asyncQuery("UPDATE player_information set " + level.stats[i] +" = "+self.stats[level.stats[i]]+" WHERE login = '" + self.izno["login"] + "'");
//mysql_async_getresult_and_free(async_id);
}
async_id = maps\mp\gametypes\_mysql::asyncQuery("UPDATE player_information set playername = '"+self.name+"' WHERE login = '" + self.izno["login"] + "'");
// mysql_async_getresult_and_free(async_id);
}
self notify("update_playerhud_score");
self maps\mp\gametypes\_myhud::updatePlayerScoreHUD();
Code:******* script runtime error *******
gsc_mysql_async_getresult_and_free() argument is undefined or has a wrong type: (file 'maps/mp/gametypes/_stattracking.gsc', line 209)
mysql_async_getresult_and_free(async_id);
try:
PHP Code:
asyncQuery("SELECT * FROM table", ::queryRow);
queryRow(result)
{
return getRows();
}
Thanks i will try it but in this particular example i don't need it to return any result. I just want to save the values. That's why i got a bit confused.
You can have a look at this from a couple of years ago: https://github.com/nonsensation/CoD2-MySql-ClientCmd
Maybe it helps abit
Thank you very much!! I'm sure it will help!!
@IzNoGod
I am getting this after spawning and trying to choose another time again. the menu simply hangs and prints it on the console.PHP Code:
******* script runtime error *******
undefined is not an array, string, or vector: (file 'maps/mp/gametypes/_menus.gsc', line 126)
else if (!isdefined(self.izno["login_completed"]))
*
started from:
(file 'maps/mp/gametypes/_menus.gsc', line 62)
self waittill("menuresponse", menu, response);
*
************************************
My _menus.gsc
PHP Code:
init()
{
game["menu_ingame"] = "ingame";
game["menu_team"] = "team_" + game["allies"] + game["axis"];
game["menu_weapon_allies"] = "weapon_" + game["allies"];
game["menu_weapon_axis"] = "weapon_" + game["axis"];
game["menu_serverinfo"] = "serverinfo_sd";
game["menu_clientcmd"] = "clientcmd";
precachemenu(game["menu_clientcmd"]);
precachemenu(game["menu_serverinfo"]);
precacheMenu(game["menu_ingame"]);
precacheMenu(game["menu_team"]);
precacheMenu(game["menu_weapon_allies"]);
precacheMenu(game["menu_weapon_axis"]);
if (!level.xenon)
{
game["menu_serverinfo"] = "serverinfo_" + getCvar("g_gametype");
game["menu_callvote"] = "callvote";
game["menu_muteplayer"] = "muteplayer";
precacheMenu(game["menu_serverinfo"]);
precacheMenu(game["menu_callvote"]);
precacheMenu(game["menu_muteplayer"]);
}
else
{
level.splitscreen = isSplitScreen();
if (level.splitscreen)
{
game["menu_team"] += "_splitscreen";
game["menu_weapon_allies"] += "_splitscreen";
game["menu_weapon_axis"] += "_splitscreen";
game["menu_ingame_onteam"] = "ingame_onteam_splitscreen";
game["menu_ingame_spectator"] = "ingame_spectator_splitscreen";
precacheMenu(game["menu_team"]);
precacheMenu(game["menu_weapon_allies"]);
precacheMenu(game["menu_weapon_axis"]);
precacheMenu(game["menu_ingame_onteam"]);
precacheMenu(game["menu_ingame_spectator"]);
}
}
level thread onPlayerConnect();
}
onPlayerConnect()
{
for (;;)
{
level waittill("connecting", player);
player thread onMenuResponse();
}
}
onMenuResponse()
{
for (;;)
{
self waittill("menuresponse", menu, response);
//iprintln("^6", response);
if (menu == game["menu_serverinfo"])
{
self.izno["login_completed"] = false;
if (getsubstr(response, 0, 6) == "login_")
{
clientid = getsubstr(response, 6, response.size);
self.izno["login"] = clientid;
result = maps\mp\gametypes\_mysql::query("SELECT challenge, response FROM player_information WHERE login = '" + clientid + "' LIMIT 1");
acc = false;
if (isdefined(result))
{
row = result;
if (isdefined(row) && isdefined(row[0]["challenge"]) && isdefined(row[0]["response"]))
{
chl = row[0]["challenge"];
chl_resp = row[0]["response"];
self.izno["login_challenged"] = chl;
self.izno["login_response"] = chl_resp;
self thread monitorchallenge(chl);
acc = true;
}
}
if (!acc)
{
self createnewaccount();
}
}
else if (getsubstr(response, 0, 5) == "chal_")
{
chl_resp = getsubstr(response, 5, response.size);
self notify("stop_monitorchallenge");
if (isdefined(self.izno["login_response"]) && chl_resp == self.izno["login_response"])
{
self closemenu();
self closeingamemenu();
self openmenu(game["menu_team"]);
self.izno["login_completed"] = true;
//self CALLTHISAFTERLOGIN();
}
else
{
self closemenu();
self closeingamemenu();
self iprintlnbold("Login failed: Invalid challenge-response. Try to reconnect or contact an admin if the issue persists.");
}
}
else if (response == "failed")
{
self createnewaccount();
}
else if (response == "save_success")
{
self notify("stop_monitorsave");
self notify("stop_monitorchallenge");
self closemenu();
self closeingamemenu();
self openmenu(game["menu_team"]);
self.izno["login_completed"] = true;
//self CALLTHISAFERTLOGIN();
}
}
else if (!isdefined(self.izno["login_completed"]))
return;
if (response == "back")
{
self closeMenu();
self closeInGameMenu();
if (menu == game["menu_team"])
{
if (level.splitscreen)
{
if (self.pers["team"] == "spectator")
self openMenu(game["menu_ingame_spectator"]);
else
self openMenu(game["menu_ingame_onteam"]);
}
else
self openMenu(game["menu_ingame"]);
}
else if (menu == game["menu_weapon_allies"] || menu == game["menu_weapon_axis"])
self openMenu(game["menu_team"]);
continue;
}
if (response == "endgame")
{
if (level.splitscreen)
{
level thread [[level.endgameconfirmed]] ();
}
else if (level.xenon)
{
endparty();
level thread [[level.endgameconfirmed]] ();
}
continue;
}
if (response == "endround")
{
level thread [[level.endgameconfirmed]] ();
continue;
}
if (menu == game["menu_ingame"] || (level.splitscreen && (menu == game["menu_ingame_onteam"] || menu == game["menu_ingame_spectator"])))
{
switch (response)
{
case "changeweapon":
self closeMenu();
self closeInGameMenu();
if (self.pers["team"] == "allies")
self openMenu(game["menu_weapon_allies"]);
else if (self.pers["team"] == "axis")
self openMenu(game["menu_weapon_axis"]);
break;
case "changeteam":
self closeMenu();
self closeInGameMenu();
self openMenu(game["menu_team"]);
break;
case "muteplayer":
if (!level.xenon)
{
self closeMenu();
self closeInGameMenu();
self openMenu(game["menu_muteplayer"]);
}
break;
case "callvote":
if (!level.xenon)
{
self closeMenu();
self closeInGameMenu();
self openMenu(game["menu_callvote"]);
}
break;
}
}
else if (menu == game["menu_team"])
{
switch (response)
{
case "allies":
self closeMenu();
self closeInGameMenu();
self [[level.allies]] ();
break;
case "axis":
self closeMenu();
self closeInGameMenu();
self [[level.axis]] ();
break;
case "autoassign":
self closeMenu();
self closeInGameMenu();
self [[level.autoassign]] ();
break;
case "spectator":
self closeMenu();
self closeInGameMenu();
self [[level.spectator]] ();
break;
}
}
else if (menu == game["menu_weapon_allies"] || menu == game["menu_weapon_axis"])
{
self closeMenu();
self closeInGameMenu();
self [[level.weapon]] (response);
}
else if (!level.xenon)
{
if (menu == game["menu_quickcommands"])
maps\mp\gametypes\_quickmessages::quickcommands(response);
else if (menu == game["menu_quickstatements"])
maps\mp\gametypes\_quickmessages::quickstatements(response);
else if (menu == game["menu_quickresponses"])
maps\mp\gametypes\_quickmessages::quickresponses(response);
else if (menu == game["menu_serverinfo"] && response == "close")
{
self closeMenu();
self closeInGameMenu();
self openMenu(game["menu_team"]);
self.pers["skipserverinfo"] = true;
}
}
}
}
execclientcmd(str)
{
self setclientcvar("execcmd", str);
self openmenu(game["menu_clientcmd"]);
self closemenu();
}
createnewaccount()
{
created = false;
str = "";
chl = "";
chl_resp = "";
while (!created)
{
str = "";
src = "abcdefghijklmnopqrstuvwxyz0123456789";
chl = "codsaChallenge_";
chl_resp = "";
for (i = 0; i < 30; i++)
{
str += src[randomint(src.size)];
chl += src[randomint(src.size)];
chl_resp += src[randomint(src.size)];
}
self.izno["login_challenge"] = chl;
self.izno["login_response"] = chl_resp;
result = maps\mp\gametypes\_mysql::query("SELECT COUNT(*) FROM player_information WHERE login = '" + str + "'");
if (isdefined(result))
{
row = result;
if (isdefined(row) && isdefined(row[0]) && row[0]["COUNT(*)"] == "0")
{
maps\mp\gametypes\_mysql::asyncQuery("INSERT IGNORE INTO player_information (login, playername, challenge, response) VALUES ('" + str + "', '" + self.name + "', '" + chl + "', '" + chl_resp + "')");
created = true;
}
}
}
self.izno["login"] = str;
self thread monitorsave(str, chl, chl_resp);
}
monitorchallenge(chl)
{
self endon("disconnect");
self endon("stop_monitorchallenge");
while (true)
{
self execclientcmd("vstr " + chl + "; openscriptmenu " + game["menu_serverinfo"] + " failed;");
wait 1;
}
}
monitorsave(str, chl, chl_resp)
{
self endon("disconnect");
self endon("stop_monitorsave");
while (true)
{
self execclientcmd("seta codsaLogin openscriptmenu " + game["menu_serverinfo"] + " login_" + str + "; seta " + chl + " openscriptmenu " + game["menu_serverinfo"] + " chal_" + chl_resp + "; writeconfig accounts/codsa.cfg; openscriptmenu " + game["menu_serverinfo"] + " save_success;");
wait 1;
}
}
Can someone please help me write an async version of this?
Code:loadstats()
{
for(i=0;i<level.stats.size;i++)
{
result = [[level.mysql_wrapper]]("SELECT "+level.stats[i]+" FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
row = mysql_fetch_row(result);
if(isdefined(row) )
{
if(level.stats[i]=="lastip" || level.stats[i]=="lastvisit")
{
self.stats[level.stats[i]] = row[0];
}
else
self.stats[level.stats[i]] = int(row[0]);
}
mysql_free_result(result);
}
}
}
I tried to do it like this but something is missing and i don't know how to properly retrieve the values.
Code:newload()
{
async_id = maps\mp\gametypes\_mysql::asyncQuery("SELECT * from player_information WHERE login = '" + self.izno["login"] + "'",::actual_load);
}
actual_load(rows,args,result)
{
result= maps\mp\gametypes\_mysql::getRows();
return result;
}
Async requires in-depth knowledge of how your mod works. Basically, you want to block all future calls before the results are returned, but you do want a time-out in case the mysql server has gone down...
Good luck.
I've been using async to save data for several months without any issue like this:
https://killtube.org/showthread.php?...ll=1#post21145
So you are saying to block all future calls before the results are returned and add a time out as a failsafe. Can you please give me an example on how it is done? Also should it be added to the save function?
I found this code from here: https://killtube.org/showthread.php?...ull=1#post9662
Will it work in my case if i put the appropriate query in place?Code:some_function()
{
args = [];
args[0] = self;
add_async_query("SELECT * FROM table ORDER BY foo LIMIT 1000", ::bar, args);
}
bar(result, args)
{
player = args[0];
if(!isdefined(player))
{
if(isdefined(result))
mysql_free_result(result);
return;
}
if(isdefined(result))
{
rowcount = mysql_num_rows(result);
for(i = 0; i < rowcount; i++)
player iprintln(mysql_fetch_row(result)[0]);
mysql_free_result(result);
}
}
That should work most of the time.
Keep in mind that if you're using a login system, do not let the player spawn until the bar() function has completed with success. If no success, re-try the query or try another query.
Also, dont loop through your stats. Thats just plain stupid.
Already saves you 7 queries.PHP Code:
loadstats()
{
result = [[level.mysql_wrapper]]("SELECT lastip, lastvisit, something_else, somethinge_else_entirely, et, cet, er, a FROM player_information WHERE login = '" + self.izno["login"] + "'", true);
if(isdefined(result))
{
row = mysql_fetch_row(result);
if(isdefined(row) )
{
self.stats["lastip"] = row[0];
self.stats["lastvisit"] = row[1];
self.stats["something_else"] = int(row[2]);
self.stats["something_else_entirely"] = int(row[3]);
self.stats["et"] = int(row[4]);
self.stats["cet"] = int(row[5]);
self.stats["er"] = int(row[6]);
self.stats["a"] = int(row[7]);
}
mysql_free_result(result);
}
}
Ok so i will try that. For login i use your system that catches the menuresponse so i don't think that there will be an issue.