513 lines
16 KiB
Text
513 lines
16 KiB
Text
// Static handler responsible for some special stuff
|
|
|
|
// save version holder
|
|
Class SWWMSaveVerData : SWWMStaticThinker
|
|
{
|
|
String ver;
|
|
int uid;
|
|
}
|
|
|
|
Class SWWMStaticHandler : StaticEventHandler
|
|
{
|
|
// crash handler
|
|
ui bool wasinmap;
|
|
ui int timer, msgpick;
|
|
// versioning
|
|
bool tainted;
|
|
String taintver;
|
|
int uid;
|
|
int checktic;
|
|
int maptime;
|
|
bool unloading;
|
|
ui Dictionary menustate; // used by Demolitionist Menu to restore old menu positions
|
|
// title stuff
|
|
ui bool titlefirst;
|
|
// map title stuff
|
|
int mttics;
|
|
// warnings
|
|
bool mpwarned;
|
|
// checks
|
|
ThinkerIterator sti;
|
|
// for intermissions, to prevent repetition
|
|
ui Array<int> lasttip, lastart;
|
|
// stupid dumb thing
|
|
ui int aprcheck;
|
|
ui Font aprfnt;
|
|
|
|
override void NewGame()
|
|
{
|
|
// set save version every new session
|
|
let svd = new("SWWMSaveVerData");
|
|
svd.ChangeStatNum(Thinker.STAT_STATIC);
|
|
svd.ver = StringTable.Localize("$SWWM_SHORTVER");
|
|
uid = 0;
|
|
}
|
|
|
|
override void WorldUnloaded( WorldEvent e )
|
|
{
|
|
SWWMHandler.ClearAllShaders();
|
|
unloading = true;
|
|
}
|
|
|
|
override void WorldTick()
|
|
{
|
|
if ( mttics > 0 ) mttics--;
|
|
maptime++;
|
|
// in case we start late?
|
|
if ( multiplayer && !mpwarned )
|
|
{
|
|
mpwarned = true;
|
|
Console.Printf("\cgWARNING:\c- Multiplayer is no longer officially supported, desyncs and other issues may potentially happen. You are on your own.");
|
|
S_StartSound("compat/warn",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
// sanity check
|
|
Array<Thinker> stinkers;
|
|
if ( !sti ) sti = ThinkerIterator.Create("SWWMStaticThinker");
|
|
else sti.Reinit();
|
|
Thinker t;
|
|
while ( t = sti.Next() ) stinkers.Push(t);
|
|
if ( stinkers.Size() > 0 )
|
|
{
|
|
for ( int i=0; i<stinkers.Size(); i++ ) Console.Printf("%s is not STAT_STATIC!",stinkers[i].GetClassName());
|
|
ThrowAbortException("Panic! %d static thinker%s been tampered with!",stinkers.Size(),(stinkers.Size()==1)?" has":"s have");
|
|
}
|
|
}
|
|
|
|
override void WorldLoaded( WorldEvent e )
|
|
{
|
|
if ( gamestate != GS_TITLELEVEL )
|
|
mttics = 10; // count down to show the "area name"
|
|
unloading = false;
|
|
maptime = 0;
|
|
if ( e.IsSavegame || e.IsReopen )
|
|
{
|
|
// restore underwater sounds for players
|
|
for ( int i=0; i<MAXPLAYERS; i++ )
|
|
{
|
|
if ( !playeringame[i] || !(players[i].mo is 'Demolitionist') ) continue;
|
|
Demolitionist(players[i].mo).CheckUnderwaterAmb(true);
|
|
}
|
|
}
|
|
SWWMHandler.ClearAllShaders();
|
|
// force a reset of the minimap zoom in case it's set beyond safe levels
|
|
double mmz = swwm_mm_zoom;
|
|
if ( level.allmap && (mmz >= 2.) ) mmz = 2.;
|
|
else if ( mmz >= 1. ) mmz = 1.;
|
|
else mmz = .5;
|
|
CVar.FindCVar('swwm_mm_zoom').SetFloat(mmz);
|
|
if ( !e.IsSaveGame ) return;
|
|
// save version checker
|
|
tainted = false;
|
|
taintver = "";
|
|
checktic = gametic+5;
|
|
let ti = ThinkerIterator.Create("SWWMSaveVerData",Thinker.STAT_STATIC);
|
|
let svd = SWWMSaveVerData(ti.Next());
|
|
if ( !svd )
|
|
{
|
|
tainted = true;
|
|
taintver = "\cg(no version info)\c-";
|
|
uid = 0;
|
|
}
|
|
else
|
|
{
|
|
String cver = StringTable.Localize("$SWWM_SHORTVER");
|
|
if ( svd.ver != cver )
|
|
{
|
|
tainted = true;
|
|
taintver = svd.ver;
|
|
}
|
|
if ( svd.uid == uid ) checktic = 0;
|
|
uid = svd.uid;
|
|
}
|
|
}
|
|
|
|
override void OnUnregister()
|
|
{
|
|
// save achievements on exit
|
|
SaveAchievements();
|
|
}
|
|
|
|
override void OnRegister()
|
|
{
|
|
// fix voice type cvar
|
|
int lmp;
|
|
Array<String> types;
|
|
for ( lmp = Wads.FindLumpFullName("swwmvoicepack.txt"); lmp != -1; lmp = Wads.FindLumpFullName("swwmvoicepack.txt",lmp+1) )
|
|
{
|
|
Array<String> lst;
|
|
lst.Clear();
|
|
String dat = Wads.ReadLump(lmp);
|
|
dat.Split(lst,"\n",0);
|
|
for ( int i=0; i<lst.Size(); i++ )
|
|
{
|
|
if ( (lst[i].Length() <= 0) || (lst[i].GetNextCodePoint(0) == 0) || (lst[i].Left(1) == "\n") || (lst[i].Left(1) == "#") ) continue;
|
|
types.Push(lst[i]);
|
|
}
|
|
}
|
|
let cv = CVar.FindCVar('swwm_voicetype');
|
|
if ( types.Find(cv.GetString()) >= types.Size() )
|
|
cv.SetString("default");
|
|
// load up the achievements
|
|
if ( swwm_achievementstate == "" ) MigrateAchievements();
|
|
else LoadAchievements();
|
|
// cache fonts
|
|
Font.GetFont("TewiFont");
|
|
Font.GetFont("TewiFontOutline");
|
|
Font.GetFont("MiniwiFont");
|
|
Font.GetFont("MiniwiFontOutline");
|
|
Font.GetFont("MiniHUDOutline");
|
|
Font.GetFont("MiniHUDShadow");
|
|
Font.GetFont("XekkasNum");
|
|
Font.GetFont("MortalFont20");
|
|
Font.GetFont("MortalFont40");
|
|
Font.GetFont("MortalFont80");
|
|
// warn: mp no longer officially maintained
|
|
if ( multiplayer )
|
|
{
|
|
mpwarned = true;
|
|
Console.Printf("\cgWARNING:\c- Multiplayer is no longer officially supported, desyncs and other issues may potentially happen. You are on your own.");
|
|
S_StartSound("compat/warn",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
// warning for unsupported
|
|
if ( Wads.FindLumpFullName("swwmgamesupported.txt") != -1 ) return;
|
|
Console.Printf(
|
|
"\cx┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\c-\n"
|
|
"\cx┃ \cr[\cgWARNING\cr] \cx┃\c-\n"
|
|
"\cx┃ \chSWWM \czGZ \cjis \cfNOT\cj compatible with the loaded IWAD. \cx┃\c-\n"
|
|
"\cx┃ \cjOnly \cfDoom\cj, \cfHeretic\cj and \cfHexen\cj are supported. \cx┃\c-\n"
|
|
"\cx┃ \cjIssues \cfCAN\cj and \cfWILL\cj happen. \cx┃\c-\n"
|
|
"\cx┃ \cr[\cgYOU ARE ON YOUR OWN\cr] \cx┃\c-\n"
|
|
"\cx┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\c-");
|
|
S_StartSound("compat/warn",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
|
|
override void RenderOverlay( RenderEvent e )
|
|
{
|
|
// silly april fools thing
|
|
if ( (aprcheck == 2) && (gamestate == GS_LEVEL) )
|
|
{
|
|
String str = "Unregistered Ultracam";
|
|
Screen.DrawText(aprfnt,Font.CR_WHITE,(Screen.GetWidth()-aprfnt.StringWidth(str)*CleanXFac_1)/2,2*CleanYFac_1,str,DTA_CleanNoMove_1,true);
|
|
}
|
|
}
|
|
|
|
override void ConsoleProcess( ConsoleEvent e )
|
|
{
|
|
if ( e.Name ~== "swwmresetmmcolors" )
|
|
{
|
|
Array<String> cvarlist;
|
|
SWWMUtility.GetCVars(cvarlist);
|
|
for ( int i=0; i<cvarlist.Size(); i++ )
|
|
{
|
|
if ( (cvarlist[i].Left(8) != "swwm_mm_")
|
|
|| (cvarlist[i].IndexOf("color") == -1)
|
|
|| (cvarlist[i] == "swwm_mm_colorset") )
|
|
continue;
|
|
CVar.FindCVar(cvarlist[i]).ResetToDefault();
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmresetcvars" )
|
|
{
|
|
Array<String> cvarlist;
|
|
SWWMUtility.GetCVars(cvarlist);
|
|
for ( int i=0; i<cvarlist.Size(); i++ )
|
|
{
|
|
// don't reset these
|
|
if ( (cvarlist[i] == "swwm_playtime")
|
|
|| (cvarlist[i] == "swwm_achievementstate")
|
|
|| (cvarlist[i] == "swwm_achievementprogress") )
|
|
continue;
|
|
CVar.FindCVar(cvarlist[i]).ResetToDefault();
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmresettooltips" )
|
|
{
|
|
CVar.FindCVar('swwm_tooltipshown').ResetToDefault();
|
|
CVar.FindCVar('swwm_tooltipnote').ResetToDefault();
|
|
}
|
|
else if ( e.Name ~== "swwmlistcvars" )
|
|
{
|
|
// debug
|
|
Array<String> cvarlist;
|
|
SWWMUtility.GetCVars(cvarlist);
|
|
for ( int i=0; i<cvarlist.Size(); i++ )
|
|
{
|
|
let cv = CVar.FindCVar(cvarlist[i]);
|
|
Console.Printf(cvarlist[i].." = "..cv.GetString());
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmgetplaytime" )
|
|
{
|
|
int val = swwm_playtime;
|
|
int sec = (val%60);
|
|
int min = ((val/60)%60);
|
|
int hour = ((val/3600)%24);
|
|
int day = val/86400;
|
|
String str = "";
|
|
if ( day ) str.AppendFormat("%d days",day);
|
|
if ( hour )
|
|
{
|
|
if ( str != "" ) str = str..", ";
|
|
str.AppendFormat("%d hours",hour);
|
|
}
|
|
if ( min )
|
|
{
|
|
if ( str != "" ) str = str..", ";
|
|
str.AppendFormat("%d minutes",min);
|
|
}
|
|
if ( sec )
|
|
{
|
|
if ( str != "" ) str = str..", ";
|
|
str.AppendFormat("%d seconds",sec);
|
|
}
|
|
if ( str == "" ) Console.Printf("No Data");
|
|
else Console.Printf(str);
|
|
}
|
|
else if ( e.Name ~== "swwmresetachievements" )
|
|
{
|
|
for ( int i=0; i<achievementinfo.Size(); i++ )
|
|
{
|
|
achievementstate.Insert(achievementinfo[i].basename,"0");
|
|
if ( achievementinfo[i].maxval )
|
|
achievementprogress.Insert(achievementinfo[i].basename,"0");
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmdumpachievements" )
|
|
{
|
|
Console.Printf("---STATE---");
|
|
let di = DictionaryIterator.Create(achievementstate);
|
|
while ( di.Next() )
|
|
Console.Printf("%s = %s",di.Key(),di.Value());
|
|
Console.Printf("---PROGRESS---");
|
|
di = DictionaryIterator.Create(achievementprogress);
|
|
while ( di.Next() )
|
|
Console.Printf("%s = %s",di.Key(),di.Value());
|
|
}
|
|
else if ( e.Name ~== "swwmgetversion" )
|
|
{
|
|
let ti = ThinkerIterator.Create("SWWMSaveVerData",Thinker.STAT_STATIC);
|
|
let svd = SWWMSaveVerData(ti.Next());
|
|
if ( svd ) Console.Printf("\cj%s\c-",svd.ver);
|
|
else Console.Printf("\cg(no version data)\c-");
|
|
if ( tainted ) Console.Printf("\cgversion mismatched\c-");
|
|
else Console.Printf("\cdversion not mismatched\c-");
|
|
}
|
|
else if ( e.Name ~== "swwmdumpthinkers" )
|
|
{
|
|
Array<Class<Thinker> > sdefs;
|
|
for ( int i=0; i<AllClasses.Size(); i++ )
|
|
{
|
|
let cls = AllClasses[i];
|
|
if ( !(cls is 'Thinker') || (cls is 'Actor') || (cls == 'Thinker') )
|
|
continue;
|
|
sdefs.Push(cls);
|
|
}
|
|
if ( !e.Args[0] )
|
|
{
|
|
// trim default gzdoom thinkers
|
|
for ( int i=0; i<sdefs.Size(); i++ )
|
|
{
|
|
if ( sdefs[i].GetClassName() != 'WallLightTransfer' )
|
|
continue;
|
|
sdefs.Delete(0,i+1);
|
|
break;
|
|
}
|
|
}
|
|
Array<int> stink;
|
|
stink.Resize(sdefs.Size());
|
|
for ( int i=Thinker.STAT_INFO; i<Thinker.MAX_STATNUM; i++ )
|
|
{
|
|
let ti = ThinkerIterator.Create("Thinker",i);
|
|
Thinker t;
|
|
while ( t = ti.Next() )
|
|
{
|
|
if ( t is 'Actor' ) continue;
|
|
let cls = t.GetClass();
|
|
let p = sdefs.Find(cls);
|
|
if ( p >= sdefs.Size() ) continue;
|
|
stink[p]++;
|
|
}
|
|
ti.Destroy();
|
|
}
|
|
for ( int i=0; i<sdefs.Size(); i++ )
|
|
Console.Printf("%s%s%s\c-",stink[i]?"\cj":"\cu",sdefs[i].GetClassName(),(stink[i]>1)?String.Format(" [%d]",stink[i]):"");
|
|
}
|
|
else if ( e.Name ~== "swwmdumphandlers" )
|
|
{
|
|
for ( int i=0; i<AllClasses.Size(); i++ )
|
|
{
|
|
let cls = AllClasses[i];
|
|
if ( !(cls is 'StaticEventHandler') || (cls == 'StaticEventHandler') || (cls == 'EventHandler') )
|
|
continue;
|
|
bool reg = (cls is 'EventHandler')?EventHandler.Find((Class<EventHandler>)(cls)):StaticEventHandler.Find((Class<StaticEventHandler>)(cls));
|
|
Console.Printf("%s%s\c-",reg?"\cj":"\cu",cls.GetClassName());
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmtestdlgsize" )
|
|
{
|
|
let f = Font.GetFont('TewiFont');
|
|
let lmp = Wads.FindLumpFullName("language.def_dlg");
|
|
Array<String> lst;
|
|
lst.Clear();
|
|
String dat = Wads.ReadLump(lmp);
|
|
dat.Split(lst,"\n",0);
|
|
bool skipme = true;
|
|
Console.Printf("[default]");
|
|
bool fail = false;
|
|
for ( int i=0; i<lst.Size(); i++ )
|
|
{
|
|
if ( lst[i].Left(7) == "// E1M8" ) skipme = false;
|
|
if ( lst[i].Left(5) != "SWWM_" ) continue;
|
|
if ( skipme ) continue;
|
|
// extract string
|
|
int st = lst[i].IndexOf("\"")+1;
|
|
int en = lst[i].RightIndexOf("\"");
|
|
String line = lst[i].Mid(st,en-st);
|
|
//line.Filter(); // DOES NOT WORK, FOR SOME REASON
|
|
line.Substitute("\\\"","\"");
|
|
line.Substitute("\\c","\c");
|
|
BrokenLines l = f.BreakLines(line,220);
|
|
if ( l.Count() > 4 )
|
|
{
|
|
Console.Printf("\cg%s [%d]\c-",lst[i].Left(st-4),l.Count());
|
|
fail = true;
|
|
}
|
|
l.Destroy();
|
|
}
|
|
if ( !fail ) Console.Printf("ALL OK");
|
|
lmp = Wads.FindLumpFullName("language.es_dlg");
|
|
lst.Clear();
|
|
dat = Wads.ReadLump(lmp);
|
|
dat.Split(lst,"\n",0);
|
|
skipme = true;
|
|
Console.Printf("[es]");
|
|
for ( int i=0; i<lst.Size(); i++ )
|
|
{
|
|
if ( lst[i].Left(7) == "// E1M8" ) skipme = false;
|
|
if ( lst[i].Left(5) != "SWWM_" ) continue;
|
|
if ( skipme ) continue;
|
|
// extract string
|
|
int st = lst[i].IndexOf("\"")+1;
|
|
int en = lst[i].RightIndexOf("\"");
|
|
String line = lst[i].Mid(st,en-st);
|
|
//line.Filter(); // DOES NOT WORK, FOR SOME REASON
|
|
line.Substitute("\\\"","\"");
|
|
line.Substitute("\\c","\c");
|
|
BrokenLines l = f.BreakLines(line,220);
|
|
if ( l.Count() > 4 )
|
|
{
|
|
Console.Printf("\cg%s [%d]\c-",lst[i].Left(st-4),l.Count());
|
|
fail = true;
|
|
}
|
|
l.Destroy();
|
|
}
|
|
if ( !fail ) Console.Printf("ALL OK");
|
|
}
|
|
}
|
|
|
|
override void NetworkProcess( ConsoleEvent e )
|
|
{
|
|
if ( e.IsManual ) return;
|
|
if ( e.Name.Left(16) ~== "swwmachievement." )
|
|
{
|
|
let c = Actor.Spawn("PartyTime",players[e.Args[0]].mo.pos);
|
|
c.bSTANDSTILL = true;
|
|
if ( e.Args[0] == consoleplayer )
|
|
{
|
|
c.A_StartSound("misc/achievement",CHAN_ITEM,CHANF_UI|CHANF_OVERLAP,attenuation:0.);
|
|
c.A_StartSound("misc/achievement2",CHAN_VOICE,CHANF_UI|CHANF_OVERLAP,attenuation:0.);
|
|
}
|
|
else
|
|
{
|
|
Console.Printf(String.Format(StringTable.Localize("$SWWM_CHEEVOREM"),players[e.Args[0]].GetUserName(),StringTable.Localize(e.Name.Mid(16))));
|
|
c.A_StartSound("misc/achievement",CHAN_ITEM,CHANF_UI|CHANF_OVERLAP);
|
|
c.A_StartSound("misc/achievement2",CHAN_ITEM,CHANF_UI|CHANF_OVERLAP);
|
|
}
|
|
}
|
|
else if ( e.Name ~== "swwmsessionid" )
|
|
{
|
|
let ti = ThinkerIterator.Create("SWWMSaveVerData",Thinker.STAT_STATIC);
|
|
let svd = SWWMSaveVerData(ti.Next());
|
|
if ( !uid ) uid = e.Args[0];
|
|
if ( svd && !svd.uid ) svd.uid = e.Args[0];
|
|
}
|
|
}
|
|
|
|
override void PostUiTick()
|
|
{
|
|
if ( !uid ) EventHandler.SendNetworkEvent("swwmsessionid",SystemTime.Now());
|
|
if ( gamestate != GS_TITLELEVEL ) titlefirst = true; // we skip it
|
|
if ( !aprcheck && (gamestate == GS_LEVEL) )
|
|
{
|
|
aprfnt = Font.GetFont("TewiFontOutline");
|
|
aprcheck = 1;
|
|
if ( SystemTime.Format("%d%m",SystemTime.Now()) == "0104" )
|
|
aprcheck = 2;
|
|
}
|
|
if ( (gametic > 0) && !(gametic%GameTicRate) )
|
|
{
|
|
let pt = CVar.FindCVar('swwm_playtime');
|
|
int ct = pt.GetInt();
|
|
pt.SetInt(ct+1);
|
|
}
|
|
if ( gamestate != GS_LEVEL ) return;
|
|
if ( (mttics == 1) && swwm_showmaptitle )
|
|
StatusBar.AttachMessage(new("DSMapTitle").Init(),-7777);
|
|
CheckAllAchievements();
|
|
if ( gametic != checktic ) return;
|
|
String cver = StringTable.Localize("$SWWM_SHORTVER");
|
|
if ( tainted )
|
|
{
|
|
let ti = ThinkerIterator.Create("SWWMSaveVerData",Thinker.STAT_STATIC);
|
|
let svd = SWWMSaveVerData(ti.Next());
|
|
if ( !svd ) Console.Printf("\cgWARNING:\n \cjSave contains no version data. Issues may happen.\c-");
|
|
else
|
|
{
|
|
Console.Printf("\cgWARNING:\n \cjVersion mismatch with save data. Issues may happen.\c-");
|
|
Console.Printf("\cgSaved:\n \cj"..svd.ver.."\c-");
|
|
Console.Printf("\cgCurrent:\n \cj"..cver.."\c-");
|
|
}
|
|
}
|
|
}
|
|
|
|
override void UiTick()
|
|
{
|
|
// Fancy crash effect
|
|
if ( (gamestate == GS_LEVEL) || (gamestate == GS_TITLELEVEL) )
|
|
{
|
|
wasinmap = true;
|
|
timer = 0;
|
|
}
|
|
else if ( (gamestate == GS_FULLCONSOLE) && ((wasinmap && !players[consoleplayer].viewheight) || (timer > 0)) )
|
|
{
|
|
wasinmap = false;
|
|
if ( timer == 1 )
|
|
{
|
|
msgpick = Random[UIStuff](1,8);
|
|
Console.Printf("\cf%s\c-",StringTable.Localize("$CRASHMSG"..msgpick.."A"));
|
|
let hnd = SWWMBrutalHandler(StaticEventHandler.Find("SWWMBrutalHandler"));
|
|
if ( hnd && hnd.detected )
|
|
{
|
|
S_StartSound("crash/glass",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
S_StartSound("crash/glass",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
else S_StartSound("crash/crash",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
else if ( timer == 70 )
|
|
{
|
|
Console.Printf("\cf%s\c-",StringTable.Localize("$CRASHMSG"..msgpick.."B"));
|
|
S_StartSound("crash/curb",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE);
|
|
}
|
|
else if ( timer == 140 )
|
|
{
|
|
let hnd = SWWMBrutalHandler(StaticEventHandler.Find("SWWMBrutalHandler"));
|
|
if ( hnd && hnd.detected ) Console.Printf("\cfYou shouldn't have tried running this with "..hnd.which..".\c-");
|
|
else Console.Printf("\cfYou should probably screenshot this error and show it to Marisa.\c-");
|
|
Console.Printf("\cfLoaded Version:\n \cj%s\c-",StringTable.Localize("$SWWM_SHORTVER"));
|
|
if ( tainted ) Console.Printf("\cfSavegame Version:\n \cj%s\c-",taintver);
|
|
}
|
|
timer++;
|
|
}
|
|
}
|
|
}
|
|
|