May 22, 2012, 05:01:09 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Please report any bugs or issues that you might be encountering with the Beta in the Support System so that we can better keep track of any oustanding issues that may come up.

GameCore Support System
 
   Home   Help Search Login Register  
Pages: 1 [2]
  Print  
Author Topic: [Example] Pickup All  (Read 1742 times)
Squat
Hero Member
*****
Posts: 592


View Profile
« Reply #15 on: September 03, 2008, 07:35:37 PM »

I'm not sure Pixel, but I know if there's anything in the game telling him to also animate, it will overwrite as soon as it's taken. Perhaps examine the idle animation code? I haven't tried to control animations yet.

I've taken the original script and revamped it into something a little more robust. I had thought about the things that it was missing and now I think it's actually kind of useful.

It still tracks the total you place by hand and reports if you win. It now starts a timer based on the respawn time and prints it to the screen. If the timer goes out, all the objects unhide and your score is set to zero. If you get them all within the time, you win and they no longer respawn. It's pretty customizable, the easiest thing being just setting canrespawn to 0 in the global controller, which kills the timer aswell.

I figure this is perfect for giving the player a particular path that he must follow within a particular time. Most often, I'd imagine this would work best with 2 objects for start and end. I plan to use it for tutorials in the timed state and regular powerups when not respawning.

I would like somebody to help me in disabling the object's collisions on hide because you still bump into them and it tosses you over the input boxes completely.

CheeseBit_Global.gsl
Quote
int cheesebits;
int count;
bool canrespawn;
bool timing;
bool showall;
float respawnTime;
float Timer;

void Initialize( Object@ object)
{
   object.SetControllerSetting("showall", 0);
   object.SetControllerSetting("respawnTime", 10); //set the total timer here
   Timer = object.GetControllerSettingFloat("respawnTime"); //grab value
   
   object.SetControllerSetting("cheesebits", 0);
   object.SetControllerSetting("count", 0);
   
   object.SetControllerSetting("canrespawn", 1); //set to 0 for no respawning or timer
   object.SetControllerSetting("timing", 0); //shut off timer
}

void DynamicsAdvance( Object@ object, float seconds)
{
   canrespawn = object.GetControllerSettingBool("canrespawn"); //grab global respawn value
   if(canrespawn==true) //only if respawn is on
   {
      
      timing = object.GetControllerSettingBool("timing"); //get timer on/off status
   
      if(timing) //only if global timer is going
      {
         if(Timer <= 1) //only if TIME UP
         {
            if(!showall) //only if NOT set to showall
            {
               object.SetControllerSetting("showall", 1); //set showall to 1
               GetGameManager().ShowTextPlain("YOU LOSE! Hint:(go faster)", 3); //report loss
            }
            Timer = object.GetControllerSettingFloat("respawnTime"); //grab global respawn time
            object.SetControllerSetting("timing", 0); //set the timer to off
         }
         else //TIME NOT UP YET
         {
            object.SetControllerSetting("showall", 0); //grab showall status
            Timer-=seconds; //delete actual game-time from local timer variable
            int convert = Timer; //convert value to integer (remove decimal places)
            String clock = ""+convert; //convert integer to string
            GetGameManager().ShowTextPlain(clock, 1); //print string value to screen
         }
      }
      else //global timer is NOT going
      {
         object.SetControllerSetting("showall", 0); //set showall status to off
         Timer = object.GetControllerSettingFloat("respawnTime"); //grab global respawn time (gets missed above if passed over)
         object.SetControllerSetting("timing", 0); //reset the timer to off
      }
   }
   
}

Cheese_Pickup.gsl
Quote
bool canrespawn;
bool timing;

bool cancount = false;

bool gotten = false; //without this, no respawn deletes all bits at start
float respawnTime; //set the time to pick up ALL items, starts counting from first item picked up and stops when 0
float timeToRespawn = 0; //don't alter, needs to be set to 0
int cheesebits = 0;

bool showall;

int countreport;
int counttotal;
bool done = false;

void Initialize( Object@ object)
{
   Object@ cheeseglobal = GetGameManager().GetWorld().GetObject("cheesebit_global"); //get handle for Global controller
   respawnTime = cheeseglobal.GetControllerSettingFloat("respawnTime");
   
   countreport = cheeseglobal.GetControllerSettingInt("count"); //pass floating count
   countreport+=1; //this object increases countreport on load ( each object does 1 time)
   cheeseglobal.SetControllerSetting("count", countreport); //update the global controller
   int counttotal = cheeseglobal.GetControllerSettingInt("count"); //get total to use in final result
   
   GetControl( "AmmoText", "FPS_HUD").SetTextPlain( "0/"+counttotal); //initiate the HUD
   GetGameManager().ShowTextPlain("THERE ARE " + counttotal + " BITS OF CHEESE!", 5); //initial message

}

void DynamicsAdvance( Object@ object, float seconds)
{
   Object@ cheeseglobal = GetGameManager().GetWorld().GetObject("cheesebit_global"); //get handle for Global controller
   showall = cheeseglobal.GetControllerSettingBool("showall");
   

   
   if(!done) //first time setup goes here
   {      
      done = true;
   }
   
   canrespawn = cheeseglobal.GetControllerSettingBool("canrespawn"); //get global respawn variable
   if(!canrespawn)
   {
      if(gotten) //only if this object is gotten already
      object.Delete(); //dumps this bit of cheese if global respawn ever goes false
   }
   
   if (object.IsVisible()) //only if it's showing
   {
      // for fun let's make it spin in circles
      //~ object.GetCurMatrix().Rotate( 1, 0, 0); //leave out with objects having mass

   }
   else
   {
      
   //..Kill this whole block if you want the bits to respawn individually based on when they were gotten. Beware timer issues.
   if(showall) //passed when timer counts to 0, every object does this at once.
   {
      object.Show(); //reveals this object
      
      //UPDATE CHEESE COUNTS AGAIN
      cheesebits = cheeseglobal.GetControllerSettingInt("cheesebits"); //pass current count from controller
      cheesebits--; //DEcrease current count by 1
      cheeseglobal.SetControllerSetting("cheesebits", cheesebits); //pass count back to controller
      int counttotal = cheeseglobal.GetControllerSettingInt("count"); //need to pass from controller again to update value
      GetControl( "AmmoText", "FPS_HUD").SetTextPlain( cheesebits + "/" + counttotal); //update hud with cheese count
   }
   //..Kill to here
   
      if (timeToRespawn > 0)
      {
         timeToRespawn -= seconds;
         if (timeToRespawn <= 0)
         {
            timeToRespawn = 0;
            object.Show();
            
            //UPDATE CHEESE COUNTS
            Object@ cheeseglobal = GetGameManager().GetWorld().GetObject("cheesebit_global"); //get handle to global controller
            cheesebits = cheeseglobal.GetControllerSettingInt("cheesebits"); //pass current count from controller
            cheesebits--; //DEcrease current count by 1
            cheeseglobal.SetControllerSetting("cheesebits", cheesebits); //pass count back to controller
            int counttotal = cheeseglobal.GetControllerSettingInt("count"); //need to pass from controller again to update value
            GetControl( "AmmoText", "FPS_HUD").SetTextPlain( cheesebits + "/" + counttotal); //update hud with cheese count
         }
      }
   }
}

bool HandleEvent( Object@ object, const String& in event, GameEventParams@ params) //handled per tick if within input box
{

   
   if(params.player != null) //player interaction
   {
      if(event == "EnterProximity") //handled one time upon entry to input box
      {
         Object@ cheeseglobal = GetGameManager().GetWorld().GetObject("cheesebit_global"); //get handle to global controller
         timing = cheeseglobal.GetControllerSettingBool("timing"); //get status of the global timer
            if(!timing) //only if the global timer is !NOT running
            {
               cheeseglobal.SetControllerSetting("timing", 1); //set the global timer to run
            }
         gotten = true; //we have gotten this item once
         
         if(object.IsVisible()) //if we are visible pickup, if not then dont
         {
         
            if(canrespawn) //only if global respawn is on
            {
               object.Hide(); //hides this bit, remains in world with collisions/scripts active
               //need code to disable collisions or inputs are sketchy on close pieces
            }
            else
            {
               object.Delete(); //deletes this bit of cheese if we can't respawn, all local scripts are deleted too
            }
               

            //UPDATE CHEESE COUNTS YET AGAIN
            cheesebits = cheeseglobal.GetControllerSettingInt("cheesebits"); //pass current count from controller
            cheesebits++; //increase current count by 1
            cheeseglobal.SetControllerSetting("cheesebits", cheesebits); //pass count back to controller
            int counttotal = cheeseglobal.GetControllerSettingInt("count"); //need to pass from controller again to update value
            GetControl( "AmmoText", "FPS_HUD").SetTextPlain( cheesebits + "/" + counttotal); //update hud with cheese count
      
            if(cheesebits == counttotal) //check if curret = total
            { //code any victory dance, reward or gameplay here
               GetGameManager().ShowTextPlain("YOU FOUND ALL " + counttotal + " BITS OF CHEESE!", 4); //Print victory to screen
               cheeseglobal.SetControllerSetting("timing", 0); //shut off timer
               cheeseglobal.SetControllerSetting("canrespawn", 0); //shut off respawn
            } //end victory code
            else
            {
               if(canrespawn) //only if global respawn is on
               {
               timeToRespawn = respawnTime; //starts respawn timer
               }
            }
         }
      }
      return true;
   }
   
   return false;
}

I still haven't tackled the fact that AI picks them up too.

I'm going to pick this up a bit later as I want to go start experimenting with raycasting, just to see if I can't maybe report the name of every object I aim at and hit P or something..with a range..and maybe report the distance. Then I want to see if we can cast rays from an object's bone direction so that if I animate an AI character looking left and right during idle, it'll affect what he sees.

Things are going to start getting pretty complicated pretty quickly here, I can see a little more clearly now. But in the end, it's always layering in what you want to happen one at a time and figuring out when to do it and how to cover your bases before and after each and every new thing is implemented, lol. It's easy.
« Last Edit: September 03, 2008, 08:44:26 PM by Squat » Logged
Ransom
Full Member
***
Posts: 132



View Profile
« Reply #16 on: September 04, 2008, 10:55:22 AM »

About animations, yes, it sounds like another animation is being called before the "victory dance" is finished.  You need a loop around the lines for the "victory dance" animation which will break when the animation is finished and go back to your idle animation.

To enable/disable collision...

Code:
object@ object.SetCollisionEnabled( bool);
« Last Edit: September 04, 2008, 11:05:40 AM by Ransom » Logged
gekido
Guest
« Reply #17 on: September 08, 2008, 12:03:53 AM »

good example, but a couple of points / hints for the future:

1) the error that people are getting is because you aren't checking if the Object Handle is valid:

ie you do:

Code:
   Object@ cheeseglobal = GetGameManager().GetWorld().GetObject("cheesebit_global"); //get handle for Global controller

and then immediately call the functions on the handle afterwards - if the handle is invalid (ie the cheesebit_global object doesn't exist for whatever reason), then the script will error out.

it is a good idea to confirm that your handles are valid before using them, as part of a standard error checking approach to scripting.  This is as simple as wrapping the following section like this:

Code:
if (cheeseglobal != null)
{
// do stuff with cheeseglobal
// basically anything that does:  cheeseglobal.CallaFunction() should be checked & wrapped like this
}

Finally you do this:

object.Delete();

but then continue to call functions / do stuff in the script afterwards - this is / can be potentially dangerous.  what object.Delete() does is puts the object on the deletion queue (and removes all scripts etc) - if you are going to call object.Delete() you need to be very careful what you do to the object afterwards - things like checking that object handles are valid etc is very important or you could easily crash the engine due to invalid pointers, null memory access and the like.

we try to catch as much as we can of this kind of thing, but particularly if you are deleting objects dynamically you need to be particularly safe about managing any outstanding object handles that you might have active.

it's safer to simply hide the objects, and might be a more 'recommended' way of doing this - just check to see if the object is hidden and ignore all processing of the object if so.  this has a couple of benefits as well:

1) if you haven't deleted objects out of the scene, it's easy to do a 'reset' of the level for save game purposes etc without having to reload the whole world
2) it's safer memory wise since you aren't deleting objects, etc...

anyways, good examples, just a few pointers to try and help out ;}

[update] - noticed that you did revise the way that you are doing the object.Delete() - the new way is much safer than what you had originally ;}


Logged
Squat
Hero Member
*****
Posts: 592


View Profile
« Reply #18 on: September 08, 2008, 02:11:18 AM »

Can I ask a question of somebody? Currently this calls directly for an object named "cheesebit" and if you don't have one or more with that name it's a problem. It shouldn't be that narrow. What would be the simplest and most efficient way to get this so that you could use the one script on any object with any name?

It's not really efficient to keep copying whole scripts for different objects, right? Does it matter much? I mean, doesn't the CPU have to run every line of script per tick anyway? Even if an object is an instance, it runs its own instance of the same script, does it really add any overhead to have it read from another one instead? It would be pretty easy to just make a coin script, cheese script, magic potion script...etc right? But still, I want a better understanding so can I get some advice on making it more open to other items, at least while my brain is fried?

But yes, great tips, thanks for those. I hadn't gotten the info I needed yet about how to disable the collisions and it was really killing the effect because the input areas weren't going off. I had the objects set in a long line with overlapping input areas is also a major part of why that happened. But Ransom came through and that's solved.

I did not, however, even once consider the issue of reseting the world or saving the progress or keeping it safe should I require the state of the world to be kept active. I'm glad you mentioned that or I'd of been screwed.

I will go in and wrap any possible nulls, but I do think I nailed them since I kept running into them about a thousand times while writing it, LOL. The good part about deleting objects though is that you can rely on the fact that it itself, its collisions, its input boxes AND its scripts are now gone.

The next part of this particular script will try to get the bits randomly spawning throughout the world. Is there any way on Earth that we can determine if a position in world space is inside of another object? If not, I was considering having one single object spawn a number of them and actually emit them in all directions and let them bounce and land where they may, run a timer and then disable them so they stay. However, I figure I can get into just as much trouble doing that if some fly into areas where the player can't reach. Hmmm.

There's also the kind where you hit like a blue coin and then it spawns a bunch of gold coins either randomly around the blue one or lays out a particular path of gold coins that sometimes reveals other secrets. Jak and Daxter do that a lot and it's not a bad mechanic. I personally think it's fun to get hit with a bunch of relatively simple challenges. My game is going to be a single player action platformer so it'll fit nicely. Not so much for RPG's.

Tell you what though, this would be create for rings in a flight sim and easy checkpoints or pickups for battle racing type games. I think it could also be expanded into a line of enemies that if get blasted before fleeing give off a pickup. You know, like in 1942 where you have to hit all 8 red planes in the formation before it gives up the 1up.
« Last Edit: September 08, 2008, 02:14:40 AM by Squat » Logged
hikmayan
Full Member
***
Posts: 231



View Profile
« Reply #19 on: September 08, 2008, 02:35:32 AM »

Nice man,thanks for sharing.
Logged

You have to be in it.....to win it!
gekido
Guest
« Reply #20 on: September 09, 2008, 12:21:43 AM »

The way to make the script more generic would be to use ControllerSetting parameters and read in a pickup Type similar to what the default pickup script does already.

Frankly you could implement the same thing as what this script does with the default pickup script and a couple lines of code in the player to count the times that the item is picked up. I think the intent was more as a test / example of what could be done more than anything though.

Just modify the section after this:

Code:
else
if (object.GetControllerSettingString( "PickupType") == "Health")
{
SetHealth( thisObject, health + object.GetControllerSettingInt("PickupHealth", 0), armour + object.GetControllerSettingInt("PickupArmour", 0));
}

And add a check for your custom pickup type:

Code:
else
if (object.GetControllerSettingString( "PickupType") == "Health")
{
SetHealth( thisObject, health + object.GetControllerSettingInt("PickupHealth", 0), armour + object.GetControllerSettingInt("PickupArmour", 0));
}
else if (object.GetControllerSettingString( "PickupType") == "Cheese")
{
       cheeseCount ++;
       GetGameManager().ShowTextPlain(" Picked up  " + cheeseCount + " piece of cheese");
}

Then elsewhere you can simply display that cheeseCount variable to the screen however you want (if you don't want to use ShowTextPlain, which you probably don't).

This way all you would need is the default pickup.gsl script, and an OPR with a controllersetting of type 'Cheese', like so:

Code:
OPRP
LoadObject pieceofcheese.obj

ControllerInputRadius 1.0000

ControllerType Scripted
ControllerSetting ScriptFile pickup.gsl
ControllerSetting PickupType Cheese
« Last Edit: September 09, 2008, 12:26:26 AM by gekido » Logged
gekido
Guest
« Reply #21 on: September 09, 2008, 12:29:00 AM »

Quote
Tell you what though, this would be create for rings in a flight sim and easy checkpoints or pickups for battle racing type games. I think it could also be expanded into a line of enemies that if get blasted before fleeing give off a pickup. You know, like in 1942 where you have to hit all 8 red planes in the formation before it gives up the 1up.

You definitely could do something like this for a multi-checkpoint system.  We've also done this using the pathfinding system and the 'rings' are literally the various segments in the road object - so each control point that you use to edit the road is basically a checkpoint for the player.  As we flesh out the scripting examples we'll have much more demonstrations / explanations of how to use the script functionality with the pathfinding to do this kind of thing.
Logged
Pages: 1 [2]
  Print  
 
Jump to:  

 
Powered by MySQL Powered by PHP bluBlur Skin © 2006, hbSkins
Powered by SMF 1.1.14 | SMF © 2006-2011, Simple Machines LLC
Valid XHTML 1.0! Valid CSS!