1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Hey Guest, is it this your first time on the forums?

    Visit the Beginner's Box

    Introduce yourself, read some of the ins and outs of the community, access to useful links and information.

    Dismiss Notice

Timers

Discussion in 'Modding Help' started by Tsilliev, Feb 16, 2016.

  1. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    So far I have tried numerous times to make a timer and each time i get different or confusing results. I tried looking around over the forums and googling around kag forums about timer, delay, I saw nothing. I tried googling around angel script, but the language there is different, and they use delayFunction or these kind of functions which I doubt are in kag.

    I have also seen different confusing examples around the scripts in Kag/base dir using, u8,u16,u32. That just make my head hurt, I just want one simple line without any connections back and forth.
    So far what i have tried...
    1. if (gametime % 600 == 0)
    I am not sure why but first time, i wait like 12 seconds which is the desired delay, second time I initiate this, i wait like 0.5 second before I get the ammo, I doubt i have to reset anything here.
    2.int diff = gametime - 870;
    if(diff > 0)
    diff = 0;
    I cannot reset the diff.

    3.
    int CountDown = CountDown + 1;
    int CountRealDown = CountDown / getTicksASecond();
    int CountMax = getTicksASecond() * 5;
    if(CountRealDown > CountMax)
    Again confusing results, if I have it getTicksASecond() * 4, I wait really short like 2 seconds, if I make it * 5 I wait 14 secs, if I make it * 6 i wait 30 seconds. I thought getTicksASecond will somehow represent what a second is, I am kind of noob, guess its something else.

    4. int CountDown;
    if(this.hasTag("Start Timer"))
    CountDown++;
    if(CountDown > 50)
    .....
    Even if I make it
    if(CountDown > 5000000000000000000000)
    It will be done in a millisecond, I am not sure if the tick frequency is that fast.

    5.
    Sleep(10);
    sleep(10);
    sleep(10.0);
    Doesnt work.

    6.TimeOut(1000);
    ...

    Can someone please show me how I can make a simple delay, that will last 10 seconds, btw this is in the OnTick, maybe I should do it in the Update?Although in all other scripts I can see time used under OnTick.
     
  2. Vermilicious

    Vermilicious Ballista Bolt Thrower

    Messages:
    232
    I'm not entirely sure what you're trying to do here (a code snippet would help), but a few tips:
    • It's usually best to use getTicksASecond() rather than x number of frames in a conditional statement, since the frame rate could be variable (or just not 60).
    • If you're writing code in an onTick handler, keep in mind that this function might or might not actually be called every single tick, or on other occasions, depending on any flags passed using this.getCurrentScript().runFlags (typically in the onInit handler).
     
    Last edited: Feb 16, 2016
  3. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    Thank you for the reply i will explain what I am trying to do in order to get the best advice possible.
    Here is the machinegun which is just a mounted bow alternative.
    Code:
    #include "VehicleCommon.as"
    #include "RulesCore.as";
    // Mounted Bow logic
    
    const Vec2f arm_offset = Vec2f(-6,0);
    
    void onInit( CBlob@ this )
    {
        Vehicle_Setup( this,
                       0.0f, // move speed
                       0.31f,  // turn speed
                       Vec2f(0.0f, 0.0f), // jump out velocity
                       false  // inventory access
                     );
        VehicleInfo@ v;
        if (!this.get( "VehicleInfo", @v )) {
            return;
        }
        Vehicle_SetupWeapon( this, v,
                             4, // fire delay (ticks)
                             1, // fire bullets amount
                             Vec2f(-6.0f, 2.0f), // fire position offset
                             "mat_bullets", // bullet ammo config name
                             "bullet", // bullet config name
                             "GunFire", // fire sound
                             "EmptyFire" // empty fire sound
                           );
        v.charge = 400;
        //this.Tag("heavy weight");
        // init arm + cage sprites
        CSprite@ sprite = this.getSprite();
        CSpriteLayer@ arm = sprite.addSpriteLayer( "arm", sprite.getConsts().filename, 16, 16 );
        //this.AddScript("RegenBullets.as"); // SCRIPT REGENBULLETSHERE----------------
        this.addCommandID("Reload");
    
        if (arm !is null)
        {
            Animation@ anim = arm.addAnimation( "default", 0, false );
            anim.AddFrame(4);
            anim.AddFrame(5);
            arm.SetOffset( arm_offset );
        }
    
        CSpriteLayer@ cage = sprite.addSpriteLayer( "cage", sprite.getConsts().filename, 8, 16 );
    
        if (cage !is null)
        {
            Animation@ anim = cage.addAnimation( "default", 0, false );
            anim.AddFrame(1);
            anim.AddFrame(5);
            anim.AddFrame(7);
            cage.SetOffset( sprite.getOffset() );
            cage.SetRelativeZ(20.0f);
        }
    
        this.getShape().SetRotationsAllowed( false );
        this.set_string("autograb blob", "mat_bullets");
    
        sprite.SetZ(-10.0f);
    
        this.getCurrentScript().runFlags |= Script::tick_hasattached;
        this.Tag("medium weight");
        // auto-load on creation
        if (getNet().isServer())
        {
            CBlob@ ammo = server_CreateBlob( "mat_bullets" );
            if (ammo !is null)    {
                if (!this.server_PutInInventory( ammo ))
                    ammo.server_Die();
            }
        }
    
    }
    
    f32 getAimAngle( CBlob@ this, VehicleInfo@ v )
    {
        f32 angle = Vehicle_getWeaponAngle(this, v);
        bool facing_left = this.isFacingLeft();
        AttachmentPoint@ gunner = this.getAttachments().getAttachmentPointByName("GUNNER");
        bool failed = true;
    
        if (gunner !is null && gunner.getOccupied() !is null)
        {
            gunner.offsetZ = 5.0f;
            Vec2f aim_vec = gunner.getPosition() - gunner.getAimPos();
    
            if( this.isAttached() )
            {
                if (facing_left) { aim_vec.x = -aim_vec.x; }
                angle = (-(aim_vec).getAngle() + 180.0f);
            }
            else
            {
                if ( (!facing_left && aim_vec.x < 0) ||
                        ( facing_left && aim_vec.x > 0 ) )
                {
                    if (aim_vec.x > 0) { aim_vec.x = -aim_vec.x; }
    
                    angle = (-(aim_vec).getAngle() + 180.0f);
                    angle = Maths::Max( -80.0f , Maths::Min( angle , 80.0f ) );
                }
                else
                {
                    this.SetFacingLeft(!facing_left);
                }
            }
        }
    
        return angle;
    }
    
    
    
    void onTick( CBlob@ this )
    {
        if (this.hasAttached() || this.getTickSinceCreated() < 30) //driver, seat or gunner, or just created
        {
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
    
            //set the arm angle based on GUNNER mouse aim, see above ^^^^
            f32 angle = getAimAngle( this, v );
            Vehicle_SetWeaponAngle( this, angle, v );
            CSprite@ sprite = this.getSprite();
            CSpriteLayer@ arm = sprite.getSpriteLayer( "arm" );
    
            if (arm !is null)
            {
                bool facing_left = sprite.isFacingLeft();
                f32 rotation = angle * (facing_left? -1: 1);
    
                if (v.loaded_ammo > 0) {
                    arm.animation.frame = 1;
                }
                else {
                    arm.animation.frame = 0;
                }
    
                arm.ResetTransform( );
                arm.SetFacingLeft(facing_left);
                arm.SetRelativeZ( 1.0f );
                arm.SetOffset( arm_offset );
                arm.RotateBy( rotation, Vec2f(facing_left?-4.0f:4.0f,0.0f) );
            }
    
    
            Vehicle_StandardControls( this, v );
        }
        //const int team = this.getTeamNum();
         //!
        const int gametime = getGameTime();
        //const int CountMax = 3 * getTicksASecond();
        //const u8 CoutMax = 10;
                if(this.hasTag("Start Timer"))
                {
                    //const int gametime = getGameTime();
                    //int diff = gametime - 870;
                    //u8 CountDown = CountDown + 1;
    
                    //int CountRealDown = CountDown / getTicksASecond();
                    //if (CountRealDown > CountMax)
            
                       if (gametime % 598 == 0)
                               {
                    print("START TIMER");
                
                    this.Tag("Zero");
                    this.Untag("Start Timer");
                    //CountDown = 0;
                    //this.set_u8(CountDown, alert);
                    //this.set_u32(freq, 0);
                     //sleep(10.0);
                               }
                }
                    if(this.hasTag("Zero"))
                    {
                
                    CBlob@ ammo = server_CreateBlob( "mat_bullets" );
                    if (ammo !is null)    {
                        if (!this.server_PutInInventory( ammo ))
                        ammo.server_Die();
    
    
                                        }
                                this.Untag("Zero");
                            
                    }
                //s32 timer = this.get_s32("explosion_timer") - gametime;
                //SColor lightColor = SColor(255, 255, Maths::Min(255, uint(gametime * 0.7)), 0);
            if(this.hasTag("Fire"))
            {
        
            //sparks(this.getPosition(), this.getAngleDegrees(), 1.5f + (XORRandom(10) / 5.0f), SColor(255, 255, 240, 171));
            }
    }
    
    void ReloadBulelts ()
    
    void onHealthChange( CBlob@ this, f32 oldHealth )
    {
    
        f32 hp = this.getHealth();
        f32 max_hp = this.getInitialHealth();
        int damframe = hp < max_hp * 0.4f ? 2 : hp < max_hp * 0.9f ? 1 : 0;
        CSprite@ sprite = this.getSprite();
        sprite.animation.frame = damframe;
        CSpriteLayer@ cage = sprite.getSpriteLayer( "cage" );
        if (cage !is null)    {
            cage.animation.frame = damframe;
        }
    }
    
    void GetButtonsFor( CBlob@ this, CBlob@ caller)
    {
        CBitStream params;
            params.write_u16(caller.getNetworkID());
            CInventory@ inv = this.getInventory();
            //CBlob@ item = inv.getItem();
            //const string itemname = item.getName();
            //const string Ammoz = "mat_bullets";
        
        if (!Vehicle_AddFlipButton( this, caller))
        {
           // Vehicle_AddLoadAmmoButton( this, caller );
           //if (!Ammoz == itemname)
           if (inv.getItemsCount() == 0 && !this.hasTag("Start Timer"))
                        {
           CButton@ button = caller.CreateGenericButton("$mat_bullets$",  Vec2f(0, 0), this, this.getCommandID("Reload"), "Reload", params);
                        }
        }
        //string InvItem = this.getInventoryName("");
        //int InvQuantity = this.getQuantity();
        //CBlob@ carryBlob = this.getCarriedBlob();
        //if (InvItem != "mat_bullets")
        //if(!carryBlob.getName() == "mat_bullets")
        //{
    
        //rules.SetGlobalMessage(this.getQuantity() + this.getInventoryName(""));
        //}
    }
    
    
    bool Vehicle_canFire( CBlob@ this, VehicleInfo@ v, bool isActionPressed, bool wasActionPressed, u8 &out chargeValue ) {return false;}
    
    void Vehicle_onFire( CBlob@ this, VehicleInfo@ v, CBlob@ bullet, const u8 _unused )
    {
        if (bullet !is null)
        {
            this.Tag("Fire");
            u16 charge = v.charge;
            f32 angle = Vehicle_getWeaponAngle( this, v );
            angle = angle * (this.isFacingLeft() ? -1:1);
            angle += ((XORRandom(512) - 256) / 64.0f) * 0;
        
            Vec2f vel = Vec2f(charge/16.0f * (this.isFacingLeft() ? -1 : 1), 0.0f).RotateBy(angle)*0.7;
            bullet.setVelocity( vel );
            Vec2f offset = arm_offset;
            offset.RotateBy(angle);
            bullet.setPosition(this.getPosition() + offset*1.1f );
            // set much higher drag than archer arrow
            bullet.getShape().setDrag( bullet.getShape().getDrag() * 2.0f );
    
            //bullet.server_SetTimeToDie( -1 ); // override lock
            //bullet.server_SetTimeToDie( 0.69f );
            bullet.Tag("bow arrow");
        }
        else{
        this.Untag("Fire");
        }
    }
    
    void onCommand( CBlob@ this, u8 cmd, CBitStream @params )
    {
        if (cmd == this.getCommandID("fire blob"))
        {          
            CBlob@ blob = getBlobByNetworkID( params.read_netid() );
            const u8 charge = params.read_u8();
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
            Vehicle_onFire( this, v, blob, charge );
        }
        if (cmd == this.getCommandID("Reload"))
        {
        this.Tag("Start Timer");
        this.getSprite().PlaySound("/ReloadGun2.ogg");
            
        
        }
    }
    
    bool doesCollideWithBlob( CBlob@ this, CBlob@ blob )
    {
        return Vehicle_doesCollideWithBlob_ground( this, blob );
    }
    
    bool ExtraCollideBlobs(CBlob@ blob)
    {
        return  blob.getName() == "GoldBrick";
    }
    
    void onCollision( CBlob@ this, CBlob@ blob, bool solid )
    {
        if (blob !is null) {
            TryToAttachVehicle( this, blob );
        }
    }
    
    You can see that when the ammo in the gun disappears, I actually create a button in GetButtonsFor, which in turn executes the command "Reload" which in turn executes this.Tag("Start Timer") which initiates the timer in the OnTick. But as I said before things go wrong there.
    --- Double Post Merged, Feb 16, 2016, Original Post Date: Feb 16, 2016 ---
    So you say its best to use the tickspersecond.

    Because I am noob, i mainly watch from examples and try to modify them a bit to achieve what I want because i have really little knowledge in this language.
    I went to TDM.as and took this:
    By the way i didnt see any flags there.

    s32 warmUpTimeSeconds = cfg.read_s32("warmUpTimeSeconds", 5);
    this.warmUpTime = (getTicksASecond() * warmUpTimeSeconds);

    So first, I am not sure what this s32 is, like the other u8,u16 and so on and so forth, i am going to use an int.

    int CountDown = (getTicksASecond() * 5)

    Is this correct? And how much seconds is this? And do I just do
    if(CountDown >= X)
    ......
    CountDown = 0;

    I doubt its going to work because I bet the getTicksASecond is a constant?
     
  4. Vermilicious

    Vermilicious Ballista Bolt Thrower

    Messages:
    232
    I'm not entirely sure, because I'm not so familiar with it, but I suspect the problem could be that you tag the blob when you receive a command. Depending on whether it was the client or the server than sent the command, it might not be registered at the time you expect (the next frame). So, instead of checking if it's the right frame, check how much time has passed; something along the lines of if(gametime-lastreloadtime >= minimumreloadtime) { }

    Using int type should usually be okay. The 's' prefix simply means "signed", in other words the number can be negative. The 'u' prefix means the opposite; "unsigned". The number just means how many bits are used. I think game time is u32.

    5 * getTicksASecond() gives you the equivalent of 5 seconds in ticks/frame count. For 60 frames/second, that would be 5 * 60 = 300 frames.
     
  5. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    Thank you, this looks really similar to the necromancer script which is:
    Code:
    u32 lastFireTime = this.get_u32("last teleport");
                const u32 gametime = getGameTime();
                int diff = gametime - (lastFireTime + FIRE_FREQUENCY);
    
    
                if (diff > 0)
                {
                    ParticleZombieLightning( this.getPosition() );
                    //if (getNet().isServer())
                    {
                        this.setPosition(this.getAimPos());
                    }
                    lastFireTime = gametime;
                    this.set_u32("last teleport", lastFireTime);
    I will try to reproduce it in mine. And about the command and the caller, it works okay, I see the button i click it and i get the ammo after some time, its just the timer is a bit jinxed.
    About the client i tried both if (getNet().isServer()) after this if (getNet().isClient() well it didnt work out well.
    --- Double Post Merged, Feb 16, 2016, Original Post Date: Feb 16, 2016 ---
    Machine gun doesnt want to spawn haha, edit: omg because i forgot to change the diff variable to countdown haha, edit2: it didnt run againg because i forgot to remove a function which i forgot about!!!

    Alright finally the machine gun spawns no more syntax errors, but the ammo is spawned imediately after i push the button which is too quick for me and i need to reload for 10 seconds.
    const int FIRE_FREQUENCY = 90;
    int CountRealDown = gametime - (LastReload + FIRE_FREQUENCY);
    if(CountRealDown > 0)
    {
    .....

    I guess the fire frequency is too little? I will try to increase it and see what happens, now this is what I am speaking about I get confusing results because in the necromancer script as i recall you have to wait like around 15-20 seconds so you can use the ability again and here it takes half a second.
    When I made fire frequency not 90 but 190 it took again half a second, when I made it 1190 it took 15 seconds, now I will try to play around and make it 10-11 seconds and see if it reloads with the same amount of time each time.
    At 980 it took 13 seconds, but second reload took 20!!!
    Code:
    if(this.hasTag("Start Timer"))
                {
           
                        //const int gametime = getGameTime();
                        //int diff = gametime - 870;
                        //u8 CountDown = CountDown + 1;
                        u32 LastReload = this.get_u32("Last Reload");
                        const u32 gametime = getGameTime();
                        int CountRealDown = gametime - (LastReload + FIRE_FREQUENCY); //CountDown / getTicksASecond();
                        //if (CountRealDown > CountMax)
       
                        //if (gametime % 598 == 0)
                        if(CountRealDown > 0)
                        {
                            print("START TIMER");
           
                            this.Tag("Zero");
                            this.Untag("Start Timer");
                            LastReload = gametime;
                            this.set_u32("Last Reload", LastReload);
                        }
                    //CountDown = 0;
                    //this.set_u8(CountDown, alert);
                    //this.set_u32(freq, 0);
                     //sleep(10.0);
           
                }
    I am guessing it took longer because LastReload is no longer 0 but has a value inside, but then again why do I need to track it like this if I want the same amount of time each time?
    If i remove it, the second time I reload it reloads instantly guess its because gametime is more than 0 and need to reset the countrealdown. But how do i reset it? Like this? lol
    Code:
                if(this.hasTag("Start Timer"))
                {
               
    
                        u32 LastReload = this.get_u32("Last Reload");
                        const u32 gametime = getGameTime();
                        int CountRealDown = gametime - FIRE_FREQUENCY; //CountDown / getTicksASecond();
    
                        if(CountRealDown > 0)
                        {
                            print("START TIMER");
               
                            this.Tag("Zero");
                            this.Untag("Start Timer");
                            CountRealDown = gametime - FIRE_FREQUENCY;
                            //LastReload = gametime;
                            //this.set_u32("Last Reload", LastReload);
                        }
           
               
                }
    Nope even from the first reload, it reloaded instantly instead of waiting out this timer.

    This is so confusing, how much is gametime? How much is it after 1 second? How much is it from the beginning 0?
    I cant find anything about gametime online, I am pretty sure that future searches about gametime will show this thread only.

    edit:
    I am trying your suggestion:
    if(gametime-lastreloadtime >= minimumreloadtime)

    How much should be minimumreloadtime? 0? 10? 100? I will test now.
     
    Last edited: Feb 16, 2016
  6. Vermilicious

    Vermilicious Ballista Bolt Thrower

    Messages:
    232
    Again, I think the variable delay you're experiencing has to do with network latency. When the client performs a command call (when you press the button), a package is sent to the server over the network before the server can act upon it. Have you tried running a local host server instead?

    You also postpone actually spawning the ammo to the next tick. Here's an edited version I made. Looks okay to me.
    Code:
    const int RELOAD_FREQUENCY = 1.5; //Seconds
    
    void onInit(CBlob@ this) {
    
        //...
    
        this.set_u32("lastReloadTime", getGameTime());
    
        //...
    
    }
    
    void onCommand( CBlob@ this, u8 cmd, CBitStream @params )
    {
    
        //...
    
        if (cmd == this.getCommandID("Reload"))
        {
    
          this.Tag("tryReload");
          this.getSprite().PlaySound("/ReloadGun2.ogg"); //Might want to play this sound later
     
        }
    
        //...
    
    }
    
    void onTick( CBlob@ this )
    {
    
      //...
    
      if(this.hasTag("tryReload"))
      {
    
        u32 lastReloadTime = this.get_u32("lastReloadTime");
    
        u32 currentTime = getGameTime();
    
        if(currentTime - (lastReloadTime + RELOAD_FREQUENCY * getTicksASecond()) > 0)
        {
     
          CBlob@ ammo = server_CreateBlob( "mat_bullets" );
     
          if (ammo !is null) {
     
            if (!this.server_PutInInventory( ammo )) {
       
              ammo.server_Die();
         
            } else {
    
              this.set_u32("lastReloadTime", currentTime);
         
              this.Untag("tryReload");
         
            }
       
          }
     
     
        }
    
      }
    
    
      //...
    
    }
     
    Last edited: Feb 16, 2016
  7. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    Thank you i will try it now, i have this extra zero tag, because you can see from the getbuttonsfrom while reloading the gun I need to disable the button, otherwise player can keep pressing it, spamming the reload sound and spamming the reloading.

    Although I can untag the start timer tag when I spawn the ammo no need for another if.
    --- Double Post Merged, Feb 16, 2016, Original Post Date: Feb 16, 2016 ---
    Just tried it out and even with 10 RELOAD_FREQUENCY it loads in half a second i will try to increase it to 500.
    edit: even if its 5000 it reloads in an instant, thats why i hate these kind of hidden values like game time, freqtickpersecond

    edit: sec i had problem with brackets not sure how it didnt pick up this as syntax error
    nope still the same. it reloads instantly
    Code:
    #include "VehicleCommon.as"
    #include "RulesCore.as";
    // Mounted Bow logic
    
    const Vec2f arm_offset = Vec2f(-6,0);
    const int RELOAD_FREQUENCY = 100; //Seconds
    void onInit( CBlob@ this )
    {
        Vehicle_Setup( this,
                       0.0f, // move speed
                       0.31f,  // turn speed
                       Vec2f(0.0f, 0.0f), // jump out velocity
                       false  // inventory access
                     );
        VehicleInfo@ v;
        if (!this.get( "VehicleInfo", @v )) {
            return;
        }
        Vehicle_SetupWeapon( this, v,
                             4, // fire delay (ticks)
                             1, // fire bullets amount
                             Vec2f(-6.0f, 2.0f), // fire position offset
                             "mat_bullets", // bullet ammo config name
                             "bullet", // bullet config name
                             "GunFire", // fire sound
                             "EmptyFire" // empty fire sound
                           );
        v.charge = 400;
    
        CSprite@ sprite = this.getSprite();
        CSpriteLayer@ arm = sprite.addSpriteLayer( "arm", sprite.getConsts().filename, 16, 16 );
        this.addCommandID("Reload");
        this.set_u32("lastReloadTime", getGameTime());
        if (arm !is null)
        {
            Animation@ anim = arm.addAnimation( "default", 0, false );
            anim.AddFrame(4);
            anim.AddFrame(5);
            arm.SetOffset( arm_offset );
        }
    
        CSpriteLayer@ cage = sprite.addSpriteLayer( "cage", sprite.getConsts().filename, 8, 16 );
    
        if (cage !is null)
        {
            Animation@ anim = cage.addAnimation( "default", 0, false );
            anim.AddFrame(1);
            anim.AddFrame(5);
            anim.AddFrame(7);
            cage.SetOffset( sprite.getOffset() );
            cage.SetRelativeZ(20.0f);
        }
    
        this.getShape().SetRotationsAllowed( false );
        this.set_string("autograb blob", "mat_bullets");
    
        sprite.SetZ(-10.0f);
    
        this.getCurrentScript().runFlags |= Script::tick_hasattached; 
        this.Tag("medium weight");
        // auto-load on creation
        if (getNet().isServer())
        {
            CBlob@ ammo = server_CreateBlob( "mat_bullets" );
            if (ammo !is null)    {
                if (!this.server_PutInInventory( ammo ))
                    ammo.server_Die();
            }
        }
     
    }
    
    f32 getAimAngle( CBlob@ this, VehicleInfo@ v )
    {
        f32 angle = Vehicle_getWeaponAngle(this, v);
        bool facing_left = this.isFacingLeft();
        AttachmentPoint@ gunner = this.getAttachments().getAttachmentPointByName("GUNNER");
        bool failed = true;
    
        if (gunner !is null && gunner.getOccupied() !is null)
        {
            gunner.offsetZ = 5.0f;
            Vec2f aim_vec = gunner.getPosition() - gunner.getAimPos();
    
            if( this.isAttached() )
            {
                if (facing_left) { aim_vec.x = -aim_vec.x; }
                angle = (-(aim_vec).getAngle() + 180.0f);
            }
            else
            {
                if ( (!facing_left && aim_vec.x < 0) ||
                        ( facing_left && aim_vec.x > 0 ) )
                {
                    if (aim_vec.x > 0) { aim_vec.x = -aim_vec.x; }
    
                    angle = (-(aim_vec).getAngle() + 180.0f);
                    angle = Maths::Max( -80.0f , Maths::Min( angle , 80.0f ) );
                }
                else
                {
                    this.SetFacingLeft(!facing_left);
                }
            }
        }
    
        return angle;
    }
    
    
    
    void onTick( CBlob@ this )
    {
        if (this.hasAttached() || this.getTickSinceCreated() < 30) //driver, seat or gunner, or just created
        {
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
    
            //set the arm angle based on GUNNER mouse aim, see above ^^^^
            f32 angle = getAimAngle( this, v );
            Vehicle_SetWeaponAngle( this, angle, v );
            CSprite@ sprite = this.getSprite();
            CSpriteLayer@ arm = sprite.getSpriteLayer( "arm" );
    
            if (arm !is null)
            {
                bool facing_left = sprite.isFacingLeft();
                f32 rotation = angle * (facing_left? -1: 1);
    
                if (v.loaded_ammo > 0) {
                    arm.animation.frame = 1;
                }
                else {
                    arm.animation.frame = 0;
                }
    
                arm.ResetTransform( );
                arm.SetFacingLeft(facing_left);
                arm.SetRelativeZ( 1.0f );
                arm.SetOffset( arm_offset );
                arm.RotateBy( rotation, Vec2f(facing_left?-4.0f:4.0f,0.0f) );
            }
    
    
            Vehicle_StandardControls( this, v );
        }
        //const int team = this.getTeamNum();
         //!
     
        //const int CountMax = 3 * getTicksASecond();
        //const u8 CoutMax = 10;
                if(this.hasTag("Start Timer"))
                {
                     
                        u32 lastReloadTime = this.get_u32("lastReloadTime");
    
                        u32 currentTime = getGameTime();
    
                        if(currentTime - (lastReloadTime + RELOAD_FREQUENCY * getTicksASecond()) > 0)
                        {
                     
                            this.Untag("Start Timer");
                         
                     
             
                 
         
                 
                        CBlob@ ammo = server_CreateBlob( "mat_bullets" );
                        if (ammo !is null) 
                                {
                        if (!this.server_PutInInventory( ammo ))
                        ammo.server_Die();
                                }
     
                        }
                     
                             
                }
                //s32 timer = this.get_s32("explosion_timer") - gametime;
                //SColor lightColor = SColor(255, 255, Maths::Min(255, uint(gametime * 0.7)), 0);
            //if(this.hasTag("Fire"))
            //{
         
            //sparks(this.getPosition(), this.getAngleDegrees(), 1.5f + (XORRandom(10) / 5.0f), SColor(255, 255, 240, 171));
            //}
    }
    
    
    
    void onHealthChange( CBlob@ this, f32 oldHealth )
    {
    
        f32 hp = this.getHealth();
        f32 max_hp = this.getInitialHealth();
        int damframe = hp < max_hp * 0.4f ? 2 : hp < max_hp * 0.9f ? 1 : 0;
        CSprite@ sprite = this.getSprite();
        sprite.animation.frame = damframe;
        CSpriteLayer@ cage = sprite.getSpriteLayer( "cage" );
        if (cage !is null)    {
            cage.animation.frame = damframe;
        }
    }
    
    void GetButtonsFor( CBlob@ this, CBlob@ caller)
    {
        CBitStream params;
            params.write_u16(caller.getNetworkID());
            CInventory@ inv = this.getInventory();
            //CBlob@ item = inv.getItem();
            //const string itemname = item.getName();
            //const string Ammoz = "mat_bullets";
         
        if (!Vehicle_AddFlipButton( this, caller))
        {
           // Vehicle_AddLoadAmmoButton( this, caller );
           //if (!Ammoz == itemname)
           if (inv.getItemsCount() == 0 && !this.hasTag("Start Timer"))
                        {
           CButton@ button = caller.CreateGenericButton("$mat_bullets$",  Vec2f(0, 0), this, this.getCommandID("Reload"), "Reload", params);
                        }
        }
        //string InvItem = this.getInventoryName("");
        //int InvQuantity = this.getQuantity();
        //CBlob@ carryBlob = this.getCarriedBlob();
        //if (InvItem != "mat_bullets")
        //if(!carryBlob.getName() == "mat_bullets")
        //{
     
        //rules.SetGlobalMessage(this.getQuantity() + this.getInventoryName(""));
        //}
    }
    
    
    bool Vehicle_canFire( CBlob@ this, VehicleInfo@ v, bool isActionPressed, bool wasActionPressed, u8 &out chargeValue ) {return false;}
    
    void Vehicle_onFire( CBlob@ this, VehicleInfo@ v, CBlob@ bullet, const u8 _unused )
    {
        if (bullet !is null)
        {
            this.Tag("Fire");
            u16 charge = v.charge;
            f32 angle = Vehicle_getWeaponAngle( this, v );
            angle = angle * (this.isFacingLeft() ? -1:1);
            angle += ((XORRandom(512) - 256) / 64.0f) * 0;
         
            Vec2f vel = Vec2f(charge/16.0f * (this.isFacingLeft() ? -1 : 1), 0.0f).RotateBy(angle)*0.7;
            bullet.setVelocity( vel );
            Vec2f offset = arm_offset;
            offset.RotateBy(angle);
            bullet.setPosition(this.getPosition() + offset*1.1f );
            // set much higher drag than archer arrow
            bullet.getShape().setDrag( bullet.getShape().getDrag() * 2.0f );
    
            //bullet.server_SetTimeToDie( -1 ); // override lock
            //bullet.server_SetTimeToDie( 0.69f );
            bullet.Tag("bow arrow");
        }
        else{
        this.Untag("Fire");
        }
    }
    
    void onCommand( CBlob@ this, u8 cmd, CBitStream @params )
    {
        if (cmd == this.getCommandID("fire blob"))
        {           
            CBlob@ blob = getBlobByNetworkID( params.read_netid() );
            const u8 charge = params.read_u8();
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
            Vehicle_onFire( this, v, blob, charge );
        }
        if (cmd == this.getCommandID("Reload"))
        {
        this.Tag("Start Timer");
        this.getSprite().PlaySound("/ReloadGun2.ogg"); 
             
         
        }
    }
    
    bool doesCollideWithBlob( CBlob@ this, CBlob@ blob )
    {
        return Vehicle_doesCollideWithBlob_ground( this, blob );
    }
    
    bool ExtraCollideBlobs(CBlob@ blob)
    {
        return  blob.getName() == "GoldBrick";
    }
    
    void onCollision( CBlob@ this, CBlob@ blob, bool solid )
    {
        if (blob !is null) {
            TryToAttachVehicle( this, blob );
        }
    }
    
    I hate this programming language, its like trying to talk to a monkey lol
    edit: omg i didnt see the end of your ode lol
    sec
     
    Last edited: Feb 16, 2016
  8. Vermilicious

    Vermilicious Ballista Bolt Thrower

    Messages:
    232
    There's really not much mystery to these time functions, and certainly not anything you would have to worry about, unless any script flags are set. Did you check if there are any other scripts tampering with such things? I'm not sure what could cause these things you experience. I would suggest adding some print calls and watch the console output (in particular the time stamps).
     
  9. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    Still reloads instantly lol
    Code:
    #include "VehicleCommon.as"
    #include "RulesCore.as";
    // Mounted Bow logic
    
    const Vec2f arm_offset = Vec2f(-6,0);
    const int RELOAD_FREQUENCY = 10; //Seconds
    void onInit( CBlob@ this )
    {
        Vehicle_Setup( this,
                       0.0f, // move speed
                       0.31f,  // turn speed
                       Vec2f(0.0f, 0.0f), // jump out velocity
                       false  // inventory access
                     );
        VehicleInfo@ v;
        if (!this.get( "VehicleInfo", @v )) {
            return;
        }
        Vehicle_SetupWeapon( this, v,
                             4, // fire delay (ticks)
                             1, // fire bullets amount
                             Vec2f(-6.0f, 2.0f), // fire position offset
                             "mat_bullets", // bullet ammo config name
                             "bullet", // bullet config name
                             "GunFire", // fire sound
                             "EmptyFire" // empty fire sound
                           );
        v.charge = 400;
    
        CSprite@ sprite = this.getSprite();
        CSpriteLayer@ arm = sprite.addSpriteLayer( "arm", sprite.getConsts().filename, 16, 16 );
        this.addCommandID("Reload");
        this.set_u32("lastReloadTime", getGameTime());
        if (arm !is null)
        {
            Animation@ anim = arm.addAnimation( "default", 0, false );
            anim.AddFrame(4);
            anim.AddFrame(5);
            arm.SetOffset( arm_offset );
        }
    
        CSpriteLayer@ cage = sprite.addSpriteLayer( "cage", sprite.getConsts().filename, 8, 16 );
    
        if (cage !is null)
        {
            Animation@ anim = cage.addAnimation( "default", 0, false );
            anim.AddFrame(1);
            anim.AddFrame(5);
            anim.AddFrame(7);
            cage.SetOffset( sprite.getOffset() );
            cage.SetRelativeZ(20.0f);
        }
    
        this.getShape().SetRotationsAllowed( false );
        this.set_string("autograb blob", "mat_bullets");
    
        sprite.SetZ(-10.0f);
    
        this.getCurrentScript().runFlags |= Script::tick_hasattached;   
        this.Tag("medium weight");
        // auto-load on creation
        if (getNet().isServer())
        {
            CBlob@ ammo = server_CreateBlob( "mat_bullets" );
            if (ammo !is null)    {
                if (!this.server_PutInInventory( ammo ))
                    ammo.server_Die();
            }
        }
       
       
    }
    
    f32 getAimAngle( CBlob@ this, VehicleInfo@ v )
    {
        f32 angle = Vehicle_getWeaponAngle(this, v);
        bool facing_left = this.isFacingLeft();
        AttachmentPoint@ gunner = this.getAttachments().getAttachmentPointByName("GUNNER");
        bool failed = true;
    
        if (gunner !is null && gunner.getOccupied() !is null)
        {
            gunner.offsetZ = 5.0f;
            Vec2f aim_vec = gunner.getPosition() - gunner.getAimPos();
    
            if( this.isAttached() )
            {
                if (facing_left) { aim_vec.x = -aim_vec.x; }
                angle = (-(aim_vec).getAngle() + 180.0f);
            }
            else
            {
                if ( (!facing_left && aim_vec.x < 0) ||
                        ( facing_left && aim_vec.x > 0 ) )
                {
                    if (aim_vec.x > 0) { aim_vec.x = -aim_vec.x; }
    
                    angle = (-(aim_vec).getAngle() + 180.0f);
                    angle = Maths::Max( -80.0f , Maths::Min( angle , 80.0f ) );
                }
                else
                {
                    this.SetFacingLeft(!facing_left);
                }
            }
        }
    
        return angle;
    }
    
    
    
    void onTick( CBlob@ this )
    {
        if (this.hasAttached() || this.getTickSinceCreated() < 30) //driver, seat or gunner, or just created
        {
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
    
            //set the arm angle based on GUNNER mouse aim, see above ^^^^
            f32 angle = getAimAngle( this, v );
            Vehicle_SetWeaponAngle( this, angle, v );
            CSprite@ sprite = this.getSprite();
            CSpriteLayer@ arm = sprite.getSpriteLayer( "arm" );
    
            if (arm !is null)
            {
                bool facing_left = sprite.isFacingLeft();
                f32 rotation = angle * (facing_left? -1: 1);
    
                if (v.loaded_ammo > 0) {
                    arm.animation.frame = 1;
                }
                else {
                    arm.animation.frame = 0;
                }
    
                arm.ResetTransform( );
                arm.SetFacingLeft(facing_left);
                arm.SetRelativeZ( 1.0f );
                arm.SetOffset( arm_offset );
                arm.RotateBy( rotation, Vec2f(facing_left?-4.0f:4.0f,0.0f) );
            }
    
    
            Vehicle_StandardControls( this, v );
        }
        //const int team = this.getTeamNum();
         //!
       
        //const int CountMax = 3 * getTicksASecond();
        //const u8 CoutMax = 10;
                if(this.hasTag("tryReload"))
        {
    
                u32 lastReloadTime = this.get_u32("lastReloadTime");
    
                u32 currentTime = getGameTime();
    
                    if(currentTime - (lastReloadTime + RELOAD_FREQUENCY * getTicksASecond()) > 0)
                    {
                   
                    CBlob@ ammo = server_CreateBlob( "mat_bullets" );
                        if (ammo !is null)
                        {
                            if (!this.server_PutInInventory( ammo ))
                            {
      
                            ammo.server_Die();
        
                            }
                            else    {
    
                                    this.set_u32("lastReloadTime", currentTime);
                                    this.Untag("tryReload");
                                   
                                }                       
                       
                        }
                       
                    }
                       
                       
                       
      
                   
                           
    
    
                //s32 timer = this.get_s32("explosion_timer") - gametime;
                //SColor lightColor = SColor(255, 255, Maths::Min(255, uint(gametime * 0.7)), 0);
            //if(this.hasTag("Fire"))
            //{
           
            //sparks(this.getPosition(), this.getAngleDegrees(), 1.5f + (XORRandom(10) / 5.0f), SColor(255, 255, 240, 171));
            //}
        }
    
    }
    
    void onHealthChange( CBlob@ this, f32 oldHealth )
    {
    
        f32 hp = this.getHealth();
        f32 max_hp = this.getInitialHealth();
        int damframe = hp < max_hp * 0.4f ? 2 : hp < max_hp * 0.9f ? 1 : 0;
        CSprite@ sprite = this.getSprite();
        sprite.animation.frame = damframe;
        CSpriteLayer@ cage = sprite.getSpriteLayer( "cage" ); 
        if (cage !is null)    {
            cage.animation.frame = damframe;
        }
    }
    
    void GetButtonsFor( CBlob@ this, CBlob@ caller)
    {
        CBitStream params;
            params.write_u16(caller.getNetworkID());
            CInventory@ inv = this.getInventory();
            //CBlob@ item = inv.getItem();
            //const string itemname = item.getName();
            //const string Ammoz = "mat_bullets";
           
        if (!Vehicle_AddFlipButton( this, caller))
        {
           // Vehicle_AddLoadAmmoButton( this, caller );
           //if (!Ammoz == itemname)
           if (inv.getItemsCount() == 0 && !this.hasTag("tryReload"))
                        {
           CButton@ button = caller.CreateGenericButton("$mat_bullets$",  Vec2f(0, 0), this, this.getCommandID("Reload"), "Reload", params);
                        }
        }
        //string InvItem = this.getInventoryName("");
        //int InvQuantity = this.getQuantity();
        //CBlob@ carryBlob = this.getCarriedBlob();
        //if (InvItem != "mat_bullets")
        //if(!carryBlob.getName() == "mat_bullets")
        //{
       
        //rules.SetGlobalMessage(this.getQuantity() + this.getInventoryName(""));
        //}
    }
    
    
    bool Vehicle_canFire( CBlob@ this, VehicleInfo@ v, bool isActionPressed, bool wasActionPressed, u8 &out chargeValue ) {return false;}
    
    void Vehicle_onFire( CBlob@ this, VehicleInfo@ v, CBlob@ bullet, const u8 _unused )
    {
        if (bullet !is null)
        {
            this.Tag("Fire");
            u16 charge = v.charge;
            f32 angle = Vehicle_getWeaponAngle( this, v );
            angle = angle * (this.isFacingLeft() ? -1:1);
            angle += ((XORRandom(512) - 256) / 64.0f) * 0;
           
            Vec2f vel = Vec2f(charge/16.0f * (this.isFacingLeft() ? -1 : 1), 0.0f).RotateBy(angle)*0.7;
            bullet.setVelocity( vel );
            Vec2f offset = arm_offset;
            offset.RotateBy(angle);
            bullet.setPosition(this.getPosition() + offset*1.1f );
            // set much higher drag than archer arrow
            bullet.getShape().setDrag( bullet.getShape().getDrag() * 2.0f );
    
            //bullet.server_SetTimeToDie( -1 ); // override lock
            //bullet.server_SetTimeToDie( 0.69f );
            bullet.Tag("bow arrow");
        }
        else{
        this.Untag("Fire");
        }
    }
    
    void onCommand( CBlob@ this, u8 cmd, CBitStream @params )
    {
        if (cmd == this.getCommandID("fire blob"))
        {             
            CBlob@ blob = getBlobByNetworkID( params.read_netid() );
            const u8 charge = params.read_u8();
            VehicleInfo@ v;
            if (!this.get( "VehicleInfo", @v )) {
                return;
            }
            Vehicle_onFire( this, v, blob, charge );
        }
        if (cmd == this.getCommandID("Reload"))
        {
        this.Tag("tryReload");
        this.getSprite().PlaySound("/ReloadGun2.ogg");   
               
           
        }
    }
    
    bool doesCollideWithBlob( CBlob@ this, CBlob@ blob )
    {
        return Vehicle_doesCollideWithBlob_ground( this, blob );
    }
    
    bool ExtraCollideBlobs(CBlob@ blob)
    {
        return  blob.getName() == "GoldBrick";
    }
    
    void onCollision( CBlob@ this, CBlob@ blob, bool solid )
    {
        if (blob !is null) {
            TryToAttachVehicle( this, blob );
        }
    }
    
    Well there are no flags in this code i can check how much is the tick frequency at the gamemode.cfg, its "map_fire_update_ticks = 7"
    About the print calls, I tried adding printint(gametime) but it doesnt work out, i cant see the time and this bugs me because i cannot troubleshoot lol
     
  10. Vermilicious

    Vermilicious Ballista Bolt Thrower

    Messages:
    232
    That line in the configuration file, I suspect, has to do with fire effects, so that's probably not it. Perhaps some of the more seasoned people can point to something I'm not seeing...

    print("Current time: " + getGameTime()); works just fine for me ;o)
     
    Tsilliev likes this.
  11. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    ok i finally fixed it.
    I did print(currentTime);
    And I saw that when the game begins the getGameTime increase from 0 to infinity.
    So what I did was when I click the reload button save the getGameTime in lastreload (should have renamed it lol) and then what i do is just if(currentTime > lastreloadtime + 300) then do your stuff. This way when i click on the button i save a fixed value of the getGameTime at the moment of clicking the button and later compare it with the already ongoing time plus a small delay. Thats it nothing hard or complicated, I just needed to use print to find out how the gameTime works. Thank you for the support especially reminding me for the print.
     
  12. Geti

    Geti Please avoid PMing me (poke a mod instead) THD Team Administrator Global Moderator

    Messages:
    3,730
    Just touching on some confusion that seemed to be ongoing - ticks per second is 30, not 60, and is unlikely to change, ever (it's tied into the networking stuff and we're just not likely to do it given how much code relies on it being 30 fps).

    You do indeed need to do something like if(currentTime > lastTime + yourTimerDelay) and make sure to initialise lastTime to 0 in onInit - if you're going to have more than one instance you need to use properties or a blob-local object like the vehicle code (which you seem to be using - just a warning those scripts are a nightmare!).

    A common trap can be to use an unsigned type and then try to set it to the result of a subtraction - if this happens, you'll end up with a massive overflow and the timer will "jam". Try to use signed types for this sort of thing, it's much less error prone (s32 over u32, s16 over u16, s8 over u8, or just plain int :) ).

    Good luck! glad to see more folks collaborating on modding these days.
     
  13. Tsilliev

    Tsilliev Haxor

    Messages:
    414
    Thank you for clarifyng, i will change the u32 currentTime to s32 and make sure the lastTime is there.
    And we are thanful that KAG is so open moddable and have so many examples liying around the scripts.
     
    Last edited: Feb 18, 2016