YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

First Time Coder: Need Assistance
massivelivefun
#1 Posted : Sunday, March 12, 2017 10:49:40 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/12/2017(UTC)
Posts: 4

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
I've been making a stopwatch for my endeavors in csgo. I thought it would work flawlessly,
but I have been spending a lot of time on something that might be seen as trivial.

I'm using the Time() function that Valve provides because the lower case time() legit crashes the game.

Code:

// This legit makes the game blow up
function currentTime()
{
time();
}


However my issue is that when I try to calculate for elapsed time it comes up as 0 seconds every time.
The reason being is because the vars start and end are exactly the same when they shouldn't be.
The 'start' var should be smaller than the 'end' var, but that's never the case.

Do variables reference their assignment every time they get added, subtracted, or something.
I thought that these variables just hold values and don't update their value unless an assignment is made.

I need help with this stuff.

This is what I have so far.

Code:

class Stopwatch
{

    start = 0.0;

    constructor()
    {
        this.start = Time();
    }
    
    function getStart()
    {
        return start;
    }

}

function elapsedTime(start)
{

    local end = Time();
    return ( end - start );
    
}

function main(args)
{

    local n = args;
    
    local timer1 = Stopwatch();
    local sum1 = 0.0;
    for (local i = 1; i <= n; i++) {
        sum1 += sqrt(i);
    }
    local time1 = elapsedTime( timer1.getStart() );
    printl( format( "%e (%.2f seconds)\n", sum1, time1 ) );

    local timer2 = Stopwatch();
    local sum2 = 0.0;
    for (local i = 1; i <= n; i++) {
        sum2 += pow(i, 0.5);
    }
    local time2 = elapsedTime( timer2.getStart() );
    printl( format( "%e (%.2f seconds)\n", sum2, time2 ) );

}
absence
#2 Posted : Monday, March 13, 2017 4:24:06 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 109
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
According to documentation, Time() gets the SERVER Time. It is not documented HOW it does this, and probably isn't what you want to do.
time() is a function from the standard squirrel library and definitely should not crash the game IF the standard library is implemented (which is not necessarily true).
If the game crashes when you call for example

call_a_function_that_definitely_does_not_exist() ;

i'd assume the standard library is not implemented.

However, please also consider that time-functions are likely to have a resolution of 1 second. The stuff you actually are measuring is most probably finished far BELOW one second, hence Start and End get determined within the exact same second and of course the difference is always 0.

You should use printl("Time returns "+Time()) to output the server time to developer console, call this (manually?) every now and then to see WHAT EXACTLY this function returns to get an idea.

massivelivefun
#3 Posted : Wednesday, March 15, 2017 4:57:40 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/12/2017(UTC)
Posts: 4

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Code:
] script main(10)
Time returns (BEFORE TIMER1 CREATION): 22.3359
Time returns (Constructor): 22.3359
Start returns (Constructor: start): 22.3359
Time returns (AFTER TIMER1 CREATION): 22.3359
Time returns (AFTER TIMER1 TEST LOOP): 22.3359
Time returns (elapsedTime FUNCTION): 22.3359
End returns(elapsedTime: end ): 22.3359
Time returns (AFTER TIMER1 ELAPSEDTIME CALL): 22.3359
2.246828e+001 (0.00 seconds)
Time returns (AFTER TIMER1 PRINT): 22.34



Time returns (BEFORE TIMER2 CREATION): 22.3359
Time returns (Constructor): 22.3359
Start returns (Constructor: start): 22.3359
Time returns (AFTER TIMER2 CREATION): 22.3359
Time returns (AFTER TIMER2 TEST LOOP): 22.3359
Time returns (elapsedTime FUNCTION): 22.3359
End returns(elapsedTime: end ): 22.3359
Time returns (AFTER TIMER2 ELAPSEDTIME CALL): 22.3359
2.246828e+001 (0.00 seconds)
Time returns (AFTER TIMER2 PRINT): 22.34

] script main(10)
Time returns (BEFORE TIMER1 CREATION): 36.2109
Time returns (Constructor): 36.2109
Start returns (Constructor: start): 36.2109
Time returns (AFTER TIMER1 CREATION): 36.2109
Time returns (AFTER TIMER1 TEST LOOP): 36.2109
Time returns (elapsedTime FUNCTION): 36.2109
End returns(elapsedTime: end ): 36.2109
Time returns (AFTER TIMER1 ELAPSEDTIME CALL): 36.2109
2.246828e+001 (0.00 seconds)
Time returns (AFTER TIMER1 PRINT): 36.21



Time returns (BEFORE TIMER2 CREATION): 36.2109
Time returns (Constructor): 36.2109
Start returns (Constructor: start): 36.2109
Time returns (AFTER TIMER2 CREATION): 36.2109
Time returns (AFTER TIMER2 TEST LOOP): 36.2109
Time returns (elapsedTime FUNCTION): 36.2109
End returns(elapsedTime: end ): 36.2109
Time returns (AFTER TIMER2 ELAPSEDTIME CALL): 36.2109
2.246828e+001 (0.00 seconds)
Time returns (AFTER TIMER2 PRINT): 36.21


Okay, so I took your advice and took it one step further.
So it seems that Valve's Time() just gets the server time, SAVES IT, then just applies it to every other instance of it until the end of the function.
It will update the time when the function completes and is ran again.

As for the time() squirrel function it's not crashing the game anymore. For whatever reason, it's just not saying it's in the index.
Idk how i got the game to crash with the currentTime function above anymore.

Code:
] script crashTheGame()

AN ERROR HAS OCCURED [the index 'time' does not exist]

CALLSTACK
*FUNCTION [crashTheGame()] Stopwatch.nut line [31]
*FUNCTION [main()] unnamed line [1]

LOCALS
[this] TABLE
[this] TABLE


It's obvious that I can't use the time function from squirrel, so am I gonna have to make an actual clock.
So can I be pointed in the right direction to make something tick on the same frequency as a clock?
absence
#4 Posted : Thursday, March 16, 2017 1:14:59 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 109
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
uhm, so it's like I expected. (I'm afraid I can't afford to research how squirrel got implemented in detail in CSGO)
Basically you cannot do a clock without a time or a timer.

So let's check what's available by executing this code:

Code:
foreach (idx,val in getroottable())
{
    if (typeof val=="function") printl(idx+": "+val) ;
}


it will show you every function that is available to squirrel at root level. See if there's more than documented and maybe useful (especially see if there's "time" or something alike)

As there may be another context, you may compare to the output of

Code:

if (typeof this=="table" || typeof this=="class")
{
   foreach (idx,val in this)
   {
    if (typeof val=="function") printl(idx+": "+val) ;
   }
} else {
   printl(@"'this' is a "+typeof this) ;
}




To ease the search for possibly suitable functions and other objects, you could automate things and search for everything available that contains "time", "date" or "clock" in it by executing this: (I think you should do this first, before checking the above)

Code:

function dumpall(where,what,sep=".",sep2="") {
    if (what==this) printl(" *** this-object: "+where+"("+typeof(this)+")") ;
    local l=where.tolower() ;
    if (  l.find("time")!=null
          || l.find("date")!=null
          || l.find("clock")!=null
          || l.find("tick")!=null
       )
    {    
       printl(where+"  ("+typeof(what)+")") ;
    }
    
    where+=sep ;
    try
    {
        local cursep=sep2 ;
        switch (typeof what)
        {
            case "array": sep="["; sep2="]" ; break ;
            case "string": return ;
            default: sep="." ; sep2="" ;
        }
        foreach(idx,val in what)
        {
            dumpall(where+idx+cursep,val,sep,sep2) ;
        }
    } catch(x) { } ; //non-iterable
    
}

dumpall("::",getroottable(),"") ;
dumpall("getconsttable().",getconsttable(),"") ; //just to make sure. consts CAN be reassigned dynamically at runtime :P

lets hope there's something you can use




BTW: I think that you can use Time() to measure elapsed time between two calls by using global instances of your class. However, I'm not sure what exactly you want to achieve in the end and when and how the game does squirrel calls at all.
Therefore I'm also curious: what happens if you execute an endless loop like "while(1){};" ? ( I'd assume you're not supposed to write functions that do not return? )

massivelivefun
#5 Posted : Saturday, March 18, 2017 9:48:04 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/12/2017(UTC)
Posts: 4

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Code:
] script_execute dumpall
*** this-object: ::(table)
::CHostage.ValidateScriptScope  (native function)
::CSceneEntity.ValidateScriptScope  (native function)
::CTriggerCamera.ValidateScriptScope  (native function)
::CBasePlayer.ValidateScriptScope  (native function)
::CBaseMultiplayerPlayer.ValidateScriptScope  (native function)
::CBaseAnimating.ValidateScriptScope  (native function)
::CBaseEntity.ValidateScriptScope  (native function)
::FrameTime  (native function)
::Time  (native function)
::CEnvEntityMaker.ValidateScriptScope  (native function)
::ScriptGetBestTrainingCourseTime  (native function)
::ScriptGetValveTrainingCourseTime  (native function)
::CFuncTrackTrain.ValidateScriptScope  (native function)
::CGameCoopMissionManager.ValidateScriptScope  (native function)
::ScriptSetBestTrainingCourseTime  (native function)
::ScriptCoopResetRoundStartTime  (native function)
::CBaseFlex.ValidateScriptScope  (native function)

] script findRootFunctions()
VSquirrel_OnReleaseScope: (function : 0x074DA980)
findRootFunctions2: (function : 0x075C1700)
IncludeScript: (function : 0x074DB340)
__DumpScope: (function : 0x074DB380)
PrintHelp: (function : 0x074DA900)
RetrieveNativeSignature: (function : 0x074DA880)
Assert: (function : 0x07443880)
findRootFunctions: (function : 0x075C1F80)
Document: (function : 0x074DA8C0)
UniqueString: (function : 0x074DB280)
VSquirrel_OnCreateScope: (function : 0x074DA940)
EntFire: (function : 0x074DB240)
Msg: (function : 0x074DA840)
dumpall: (function : 0x06D80C80)
__ReplaceClosures: (function : 0x074DB300)
printl: (function : 0x074DA800)

] script findRootFunctions2()
VSquirrel_OnReleaseScope: (function : 0x074DA980)
findRootFunctions2: (function : 0x075C1700)
IncludeScript: (function : 0x074DB340)
__DumpScope: (function : 0x074DB380)
PrintHelp: (function : 0x074DA900)
RetrieveNativeSignature: (function : 0x074DA880)
Assert: (function : 0x07443880)
findRootFunctions: (function : 0x075C1F80)
Document: (function : 0x074DA8C0)
UniqueString: (function : 0x074DB280)
VSquirrel_OnCreateScope: (function : 0x074DA940)
EntFire: (function : 0x074DB240)
Msg: (function : 0x074DA840)
dumpall: (function : 0x06D80C80)
__ReplaceClosures: (function : 0x074DB300)
printl: (function : 0x074DA800)


So it looks like there isn't a lot for me to utilize in terms of a clock that's independent from the inputs of a map/level...
The original intention of this Stopwatch is for my own personal gain. The main intention was to have this stopwatch be the allotted time that I am on a map practicing my aim. It's basically the "practice" regiment that I've been doing for csgo.
I load up one training map, then run the stopwatch. When it reaches a certain time it just goes to another training map that I have designated.
As for how all that works (^), I'm not worried about that right now. I'm just trying to make this thing count up from zero, which is proving to be difficult.

I've seen examples of Time() being used in if-statements on the valve wiki for L4D2, but like the docs and you say, Time() is the how long the SERVER has been running.
https://developer.valves...Vscript_Examples#Timers

If I put five minutes as my stopwatch's duration and check the Time() through an 'if' it would not work as intended, especially when the server has been running for long than five minutes already.
At that point I would just be switching the map with another map, that or I would have to frantically type into the console the script when the map loads.

This is a documentation of most of the squirrel scripts that exist within L4D2 which I would have to assume is similar to csgo. (I noticed CBaseAnimating from the cool dumpall script you gave me, I ran it in csgo, not L4D2 by the way)
http://forums.steampower...howthread.php?t=1238461

As for your question about the while loop:
Code:
function infinite()
{
    while(1){};
}


This did nothing, it printed nothing in the console and csgo continued to work as intended.

PS: Could you look at the L4D2 timer example, specifically the second example. It's a repeating timer, and it looks like it's using a global variable. Is that similar to you talking about the "two calls by using global instances of your class". Sorry I'm a brick when it comes to understanding squirrel. All of this is still sort of new to me.
absence
#6 Posted : Sunday, March 19, 2017 3:08:00 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 109
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
yes, you need to store the time in a global you can fetch and compare to current time. For the sake of simplicity I'd use the root table

Can you attach to any entity so your script gets called automatically?

then something along the lines

Code:
function do_sime_stuff() //gets called about every 5 minutes
{
  //load next map or whatever...
}

function Think() 
{
if ("mlf_my_lasttime" in getroottable()) {  //check only when there'S a stored time
  if (Time()-::mlf_my_lasttime > 5*60.0) { //more than 5 mintes passed? (assuming "Time" is returning seconds as a float)
    do_some_stuff() ;
    ::mlf_my_lasttime<-Time() ; //store "now" time so next action is again taken in 5 minutes
  }
} else { ::mlf_my_lasttime<-Time() ; } //store for the first time
}


should do as an entity script (after you added the "Think" function for example to your player entity using AddThinkToEnt(), I assume...)


Note: I never used vscript and don't know any details about how Squirrel got integrated, I just read a bit about it and am just guessing and making assumptions. However, you need to have above "Think" function regularly called to make it work



massivelivefun
#7 Posted : Sunday, March 19, 2017 10:52:14 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/12/2017(UTC)
Posts: 4

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Code:
class Stopwatch
{

    constructor()
    {
        printl( @"Time returns (Constructor): " +  Time() );
        this.start = Time();
        printl( @"Start returns (Constructor: start): " +  start );
    }
    
    start = null;
    
    function getStart()
    {
        return start;
    }
    
    function elapsedTime3()
    {
        printl( @"elapsedTime3: " + Time() );
        printl (@"start: " + start);
        return ( Time() - start );
    }

}

this.timer3 <- null;

function one()
{
    timer3 = Stopwatch();
}

function two()
{
    printl( @"two test: " + timer3.elapsedTime3() );
}


This works...

Code:
] script_execute Stopwatch
] script one()
Time returns (Constructor): 22.7422
Start returns (Constructor: start): 22.7422
] script two()
two test: 7.42969
] script two()
two test: 15.6953
] script two()
two test: 16.3047
] script two()
two test: 16.8359
] script two()
two test: 17.2656
] script two()
two test: 17.6328
] script two()
two test: 18.0625
] script two()
two test: 18.4688
] script two()
two test: 18.8359
] script two()
two test: 20.2891
] script two()
two test: 20.8359
] script two()
two test: 21.1406
] script two()
two test: 21.5547

] script_execute Stopwatch
] script one()
Time returns (Constructor): 178.055
Start returns (Constructor: start): 178.055
] script two()
elapsedTime3: 183.469
start: 178.055
two test: 5.41406


...but I have to separate and execute the two function independently, otherwise Time() doesn't update.
Is this a problem with the 'scope' of Time()?

Just another concept I still don't have a grasp on...
absence
#8 Posted : Saturday, March 25, 2017 4:15:27 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 109
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
when a script is called, it "blocks" the caller (game engine) until it is done and returned.
The game though is expected to accept input, render the frame and communicate with the server regularly, independent on when or even whether the script is done.
These things usually are achieved using multithreading and other mechanisms, all having the need to "synchronize things".
Hence, the server time is fetched over network from the server (that's obvious, isn't it) - with no guarantee when the response will be available. When the response comes in, it is saved. However, as explained above, script calls are also indeterminate when it comes to their execution time. So when a script call is to be done, it is most probably done in a separate thread. The variable written by the thread fetching the time from the server MUST NOT be accessed by the script to avoid concurrend access. So most probably the value of the last server time is copied to a place that is SAFE to access by a script at any time (which then a call to Time() will fetch and return to the script).
Hence, as all these things happen asynchroneously, it is expected behaviour fot Time() to not change during a single script call, because if it would synchronize on every call to Time() that would block (and hence slow down) other threads that are meant to render graphics, process input, process network code and such.

This applies to more than just the server time, most probably to the whole concept of a server game state "snapshot" (which i believe is called a "frame" here) including object positions and everything needed for the game to "work" properly.

Result: To achieve your goal, you need to have a script function called regularly by the game engine, let the script get the server time of the current frame and compare it to a (global?) time you saved earlier.
I have the notion you are calling your script MANUALLY (by entering things to the console, for example) - given above synchronisation concepts that are necessarily present in a way or another, that's most probably a fruitless approach.

As I never coped with vscript I can't provide much more hints than I already did, I'm sorry.

Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.130 seconds.