Author Topic: Delayed function call with arguments?  (Read 1032 times)

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Delayed function call with arguments?
« on: August 01, 2013, 08:22:00 PM »
Title is almost self-explanatory and again i'm sure this has been brought up infinity times before.

Possible to create a delayed call to a function with pre-defined arguments?

The question to answer is, how to call a function like:
Code: [Select]
def MyFunction(pShip, flag=0, pObjectName):
print pShip
print flag
print pObjectName
with pre-determined arguments after a set amount of time?

I have been searching the BC API for hours and am yet to find anything promising.
I would really love not to have to develop a butt ugly hack workaround involving globals and middle man functions :(

When replying, please remember I am noob at this stuff.
Only ever created my timers using MissionLib.CreateTimer .

 - - - - -
Also currently searching BCS-TNG but the search feature is terribad with CAPTCHA for every search.
Someone been terrorizing the domain with bots?  :lostit:
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Delayed function call with arguments?
« Reply #1 on: August 01, 2013, 08:38:19 PM »
Before I say anything what exactly are you trying to achieve?

Quote
Someone been terrorizing the domain with bots?

Not recently. I just don't want bots overloading the database.
Acta, non verba.
aka USS Sovereign

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Delayed function call with arguments?
« Reply #2 on: August 01, 2013, 09:07:39 PM »
I'm trying to achieve a delay before the execution of code.

An event happens (a function fires ... in this case subsystemdisabled but it doesn't matter).
..... delay .....
Function to handle that event is called.

If the function is: MyFunction(arg1, arg2, arg3) then in this case I may want to call it as:
MyFunction(pShip, 0, pDisabledObjectName)
...
except after a delay of course.

The delay can't hang up the entire script or the game.

Python
import time
time.sleep()

Pauses the entire game.
Great men are not peacemakers! Great men are conquerors!

Offline CyAn1d3

  • MacDill Shipyards Design Team
  • Posts: 1656
  • Cookies: 420
  • RETIRED
Re: Delayed function call with arguments?
« Reply #3 on: August 01, 2013, 10:38:33 PM »
I'm trying to achieve a delay before the execution of code.

An event happens (a function fires ... in this case subsystemdisabled but it doesn't matter).
..... delay .....
Function to handle that event is called.

If the function is: MyFunction(arg1, arg2, arg3) then in this case I may want to call it as:
MyFunction(pShip, 0, pDisabledObjectName)
...
except after a delay of course.

The delay can't hang up the entire script or the game.

Python
import time
time.sleep()

Pauses the entire game.

if im reading this right you want to essentially "pause" the games functions after something happens like and RPG does with commands?
like if you fire off a torpedo, then the game pauses allowing you to make choices and decisions based on a set limit before everything restarts again real time?
(im following this and am interested :P)
I came, i saw, i added a Sig.
Later gents, i have Youtube to take over.
Cy - 1-12-15

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Delayed function call with arguments?
« Reply #4 on: August 02, 2013, 05:59:00 AM »
if im reading this right you want to essentially "pause" the games functions after something happens like and RPG does with commands?
like if you fire off a torpedo, then the game pauses allowing you to make choices and decisions based on a set limit before everything restarts again real time?
(im following this and am interested :P)
Wrong  :nono:

The game should not pause. The script should not pause.
The game must continue during the delay. The script must continue reacting to events and doing everything else it needs to during the delay.

Ergo, that's the reason for me mentioning MissionLib.CreateTimer(). It permits for a function to be called after a set delay (current time + delay) but does not pause the entire game or execution of the script in which it is called.

The problem with MissionLib.CreateTimer (and all timers it seems) is that they do not permit any arguments other than (pObect, pEvent)

To my knowledge all functions in BC that are triggered by a Totally Games timer have the format:
Code: [Select]
def Function(pObject, pEvent):
        #code here

The question presented in this thread is whether it is possible to call a function such as:
Code: [Select]
def MyFunction(customArg1, customArg2, customArg3):
        # use my arguments here
after a set amount of time with its arguments.

I hope I have been clear enough.
Great men are not peacemakers! Great men are conquerors!

Offline KrrKs

  • Posts: 461
  • Cookies: 25
Re: Delayed function call with arguments?
« Reply #5 on: August 02, 2013, 09:36:21 AM »
How about specifying a custom event -type/class with the needed variables?

That way you could call your function via the normal timer.
(But I have no Idea how that would work in detail - my own timer dependent scripts all resulted in an absolute mess)

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Delayed function call with arguments?
« Reply #6 on: August 02, 2013, 11:38:53 AM »
How about specifying a custom event -type/class with the needed variables?

That way you could call your function via the normal timer.
(But I have no Idea how that would work in detail - my own timer dependent scripts all resulted in an absolute mess)
I have done just that. A class that provides add / remove and storage of arguments for each call.
It's gotten quite messy but that's because i'm storing alot in the global:
key: [shipID] values: [expiredFlag, eventID, timerID, funcArgs, callSelector]
(funcArgs is a list)
and providing methods to 'cancel' the call (function checks a global and suicides if a flag isn't set), get arguments.

No doubt the way I'm doing things is not as clean as it could be but whatever, it's a hacked workaround.

I will post the code if it gets clean enough for other people to read and if somebody doesn't come up with a 'legit' method of doing this in BC.

:\
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Delayed function call with arguments?
« Reply #7 on: August 02, 2013, 08:41:24 PM »
That's pretty easy stuff :)

To oversimplify the implementation, class implementation with an internal time slice process.

I found a sample I had on my repository:
Code: [Select]
# Imports
import App

# Constants
TimerNotRunning = 0
TimerStarted = 1
TimerRunning = 2
TimerStopped = 3

# Object with an internal timer
class TimedObject:
    # Constructor, define as many parameters as you'd want
    def __init__(self, parameter1, parameter2, parameter3, delay):
        self.status = TimerNotRunning
        self.pTimer = None       
        self.param1 = parameter1
        self.param2 = parameter2
        self.param3 = parameter3   
        self.delay = delay
    def StartTimer(self):
        if not self.pTimer:
            # Start tme slice process
            self.pTimer = App.PythonMethodProcess()
            self.pTimer.SetInstance(self)
            self.pTimer.SetFunction("TimerSliceUpdate")           
            self.pTimer.SetPriority(App.TimeSliceProcess.LOW)           
            self.pTimer.SetDelay(self.delay)
            self.status = TimerStarted
    def TimerSliceUpdate(self, fTime):                                                 
        # Check if time slice process is running
        if (self.status == TimerRunning):
            # Kill instance
            self.status = TimerStopped           
            global activeTimers
            activeTimers.remove(self)                   
        # Set status to running
        elif self.status == TimerStarted:
            self.status = TimerRunning

    def GetTimerStatus(self):
        return self.status

# Keep objects in memory
activeTimers = []

Sample to initialize multiple timer instances:
Code: [Select]
for i in range(10, 0, -1):
   timedObject  = TimedObject("p1: " + str(i), "p2: " + str(i),  "p3: " + str(i), i + 5)
   timedObject.StartTimer()
   # Ensure to keep in memory
   activeTimers.append(timedObject)
Acta, non verba.
aka USS Sovereign

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Delayed function call with arguments?
« Reply #8 on: August 03, 2013, 06:29:11 AM »
Thanks Sovereign.

Just one thing though, perhaps i'm too dumb to see it, where do you actually call your function with its stored parameters?

I understand you create a class that stores some BC API class and call TimerSliceUpdate() after a delay.

Is it possible to see a snippet calling a function you defined? Say:
Code: [Select]
def CallMeWithMyArgs(arg1, arg2, arg3):
        print "arg1:", arg1
        print "arg2:", arg2
        print "arg3:", arg3
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Delayed function call with arguments?
« Reply #9 on: August 03, 2013, 08:21:33 AM »
What I gave you was a snippet to run multiple unrelated timers which "remember" certain parameters you provide. How you will handle your implementation after that point is up to you, generally it's all basic OOP stuff.

The following indicates that the timer is going to stop and is where you insert your logic.
Code: [Select]
   def TimerSliceUpdate(self, fTime):                                                
        # Check if time slice process is running
        if (self.status == TimerRunning):
            # Kill instance
            self.status = TimerStopped          
            global activeTimers
            activeTimers.remove(self)  

You can directly call a method, you can trigger an event or even this class can hold the implementation you want. It really depends on your approach and requirements.
Acta, non verba.
aka USS Sovereign

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Delayed function call with arguments?
« Reply #10 on: August 03, 2013, 08:45:46 AM »
I understand now.

Thanks :)
Great men are not peacemakers! Great men are conquerors!

Offline Defiant

  • Posts: 398
  • Cookies: 1105
    • BC: Kobayashi Maru
Re: Delayed function call with arguments?
« Reply #11 on: August 06, 2013, 03:18:05 AM »
You could have just used a Timer Action.