Game Development Community

Help with item spawning

by Stephen · in Torque 3D Beginner · 08/10/2013 (10:56 pm) · 39 replies

I found myself stuck in trying to figure out how to do a couple of things with items. I have searched the site and I haven't found anything useful but I know there is something I just can't find it.

I'm trying to figure out how to get items to randomly spawn in different locations in a area. Then if a player destroys that item then that player gets points to their score. A good example of this would be a shooting range. Targets spawn randomly and then player destroys it and gets points.
Page «Previous 1 2
#1
08/11/2013 (1:21 am)
I would look at the player spawner code. Then create a new item and call it a TargetSpawnMarker and create a group for it. Then you can make some logic at the appropriate time in your game to place targets at that location and have it mimic the spawner position and rotation. That way you can edit the spawner position and location using the TargetSpawnMarker, but it will be invisible in game. You will have to determine how you will manage the life cycle of the targets and what triggers their spawning in the first place, if/when they respawn, etc.
#2
08/11/2013 (10:37 am)
to make it random:

drop a spwanSphere in that palace.
edit it's radius value,so that it can cover whole area.

to find an empty space in between that sphere, use this function ("scriptsserverbotAi.cs"):
"function getEmptyPlace(%objectToSpawn, %locationTransform,%locationRadius)"

it will return transform depending size of "objectToSpawn".

then create your item and set it's transform as %locationTransform.
#3
08/11/2013 (4:47 pm)
I was thinking something like this,
function TargetDummy::onDamage(%this,%obj)  
{
   echo("StaticShapeData::onDamage("@ %data @", "@ %obj @")"); 
   
   %damageAmt = %obj.getDamageLevel();  
   if (%damageAmt >= %this.destroyedLevel)  
   {
      // spawn a new object at the intersection point  
      %obj = new ItemData()  
      {
         shapeName = "art/shapes/items/misc/coin.dts";  
      };  
      // Add the new object to the MissionCleanup group  
      MissionCleanup.add(%obj);
      
      %obj.setDamageState(Destroyed);  
   }  
}
So when the player destroys the dummy it spawns a coin that the player can pick up. Or maybe something like this,
function TargetDummy::onDamage(%this,%obj)  
{
   echo("StaticShapeData::onDamage("@ %data @", "@ %obj @")"); 
   
   %damageAmt = %obj.getDamageLevel();  
   if (%damageAmt >= %this.destroyedLevel)  
   {
      %game.incScore( %sourceClient, 1, true );
      
      %obj.setDamageState(Destroyed);  
   }  
}
#4
08/11/2013 (5:08 pm)
hmmm, you could also locate the target somewhere the player can't see and then just set the location to a place he could. Just a thought. (No flaming please!)
#5
08/11/2013 (5:26 pm)
Here's some asset functions from my Tribes 2 Days that helped me do things like that. Feel free to use them! You'll just need some vector math with them to get the job done. I think RMPG() will only work if you have a missionArea object, but the getTerrainHeight function will probably be the most important here in terms of getting the 'z' position correct.

function GetRandomPosition(%mult,%nz) {
   %x = getRandom()*%mult;
   %y = getRandom()*%mult;
   %z = getRandom()*%mult;

   %rndx = getrandom(0,1);
   %rndy = getrandom(0,1);
   %rndz = getrandom(0,1);

   if(%nz) {
      %z = 0;
   }

   if (%rndx == 1){
      %negx = -1;
   }
   if (%rndx == 0){
      %negx = 1;
   }
   if (%rndy == 1){
      %negy = -1;
   }
   if (%rndy == 0){
      %negy = 1;
   }
   if (%rndz == 1){
      %negz = -1;
   }
   if (%rndz == 0){
      %negz = 1;
   }

   %rand = %negx * %x SPC %negy * %y SPC %Negz * %z;
   return %rand;
}

function RMPG() {
   %X = getWord(MissionArea.getArea(), 0);
   %Y = getWord(MissionArea.getArea(), 1);
   %W = getWord(MissionArea.getArea(), 2);
   %H = getWord(MissionArea.getArea(), 3);

   %OppX = ((%X) + (%W));
   %OppY = ((%Y) + (%H));
   %Position = getRandom(%X, %OppX) SPC getRandom(%Y, %OppY) SPC 0;

   %Z = getTerrainHeight(%position);
   %PositionF = getWord(%Position, 0) SPC getWord(%Position, 1) SPC %Z;

   return %PositionF;
}
#6
08/11/2013 (8:13 pm)
function TargetDummy::onDamage(%this,%obj)  
{
   echo("StaticShapeData::onDamage("@ %data @", "@ %obj @")"); 
   
   %damageAmt = %obj.getDamageLevel();  
   if (%damageAmt >= %this.destroyedLevel)  
   {
      // spawn a new object at the intersection point  
      %newObj = new ItemData()  //vvvvvvv-----do not mess up  %obj with this new created object.5obj refers to the object that is going to destroy.clear?
      {
         shapeName = "art/shapes/items/misc/coin.dts";  
      };  

%trans=%obj.getTransform();//add this
%newObj.setTransform(%trans);//add this

      // Add the new object to the MissionCleanup group  
      MissionCleanup.add(%obj);
      
      %obj.setDamageState(Destroyed);  
   }  
}
#7
08/11/2013 (8:20 pm)
Just a little FYI, you're probably going to need a datablock at some point for the item in order for your players to be able to pick it up, less you feel like being a redundant coder and coding the pickup code directly to the shape itself.
#8
08/11/2013 (8:49 pm)
I getting,
art/datablocks/StaticShapes/StaticShapeObjects.cs (80): Unknown command setTransform.
  Object (4647) ItemData -> ShapeBaseData -> GameBaseData -> SimDataBlock -> SimObject
#9
08/12/2013 (9:11 am)
what is the output for this line:

echo("StaticShapeData::onDamage("@ %data @", "@ %obj @")");
?
#10
08/13/2013 (9:42 am)
Datablocks don't have a location - or a transform - you need to call setTransform() on the created object....
#11
08/13/2013 (1:12 pm)
How would you do that?
#12
08/13/2013 (1:24 pm)
%newObj = new Item(){
  datablock="ItemData"; // or some other datablock that has the coin shape associated with it.  define the datablock somewhere else, like through the editor
};

Edit:
Some of the code posted is broken in the above examples (could be in mine too) so think about what each variable is supposed to represent. Don't just blindly plug in code. For instance the above code has this:
// this describes what you want to do, but the code is using the old object
// Add the new object to the MissionCleanup group    
MissionCleanup.add(%obj);  

// it should be this
// Add the new object to the MissionCleanup group    
MissionCleanup.add(%newObj);
#13
08/14/2013 (5:41 pm)
I can get the item to spawn and the player can pick it up and gets a point but the problem is the item does not disappear after the player collides with it.

function TargetDummy::onDamage(%this,%obj,%newObj)  
{
   echo("StaticShapeData::onDamage("@ %data @", "@ %obj @")"); 
   
   %damageAmt = %obj.getDamageLevel();  
   if (%damageAmt >= %this.destroyedLevel)  
   {
      %newObj = new Item()
      {  
         datablock="Coin"; // or some other datablock that has the coin shape associated with it.  define the datablock somewhere else, like through the editor  
      };     
  
      %trans=%obj.getTransform();//add this  
      %newObj.setTransform(%trans);//add this  
  
      // this describes what you want to do, but the code is using the old object  
      // Add the new object to the MissionCleanup group      
      MissionCleanup.add(%obj);    
  
      // it should be this  
      // Add the new object to the MissionCleanup group      
      MissionCleanup.add(%newObj);
      
      %obj.setDamageState(Destroyed);  
   }  
}
function Coin::onCollision(%this,%obj,%col)  
{  
   if(%col.getType() & ($TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType))  
   {  
      %col.client.incScore(%this.scoreValue);  
      %col.client.setScoreAmountHud(%col.client.score);  
  
      messageClient(%col.client, 'MsgItemPickup', '\c1You got %1 points!!', %this.scoreValue);  

      if (%col.client.score >= $Game::EndGameScore)  
         cycleGame();  
  
         return;  
   }
}
#14
08/14/2013 (5:58 pm)
What does your "Coin" datablock look like?

I don't think you need "MissionCleanup.add(%obj);". That is the old item and should have already been added by this point in the code. It does not hurt it though.

Do you have the Torque3D Script Manual? Search of Item and ItemData and it will give you more details. I am not sure why it is not showing from this code you have posted either.

I think you are getting really close though.
#15
08/14/2013 (6:05 pm)
datablock ItemData(Coin)
{
   // Mission editor category, this datablock will show up in the
   // specified category under the "shapes" root category.
   category = "Coins";

   className = "Coin";

   // Basic Item properties
   shapeFile = "art/shapes/items/coin.dts";
   mass = 2;
   friction = 1;
   elasticity = 0.3;
   emap = true;

   // Dynamic properties defined by the scripts
   pickupName = "scored 5 points";
   scoreValue = 5;
};
#16
08/14/2013 (6:24 pm)
I can think of one reason why this might not be showing. If the original object was on or slightly below the terrain/objects in that location then this might have fallen through the ground. The item was not set to static for its physics. So you should look at getting the position of the transform and modifying the height slightly to make sure the coin in above the terrain/objects that might be there. If you don't want the object to move (slide down a hill) then you need to set it to static. Add this attribute to the new object: static = true; if you don't want it to move on you.

#17
08/14/2013 (6:27 pm)
Once the player destroys the dummy the coin appears. When the player goes to the coin the player gets the point but the coin does not disappear after the player has went to it.

I'm not having any problems with spawning the item anymore but with it getting to disappear after the player collides with it. Just like the health patch.
#18
08/14/2013 (6:40 pm)
Ah, okay, that makes sense. I would schedule a delete on the Coin in the onCollision routine then. There is nothing in there telling the coin to disappear. You don't want to call delete directly on the coin item.

Also, if that return is supposed to be part of the if then the code is wrong:
if (%col.client.score >= $Game::EndGameScore)    
{
    cycleGame();    
    
    return;   
}

In onCollision the %obj variable is the actual item. Where the %this is the Coin datablock. So you would schedule delete on the %obj. Search for schedule in the Torque 3D Script manual. There should be examples for using it. Also, use 0 (zero) time so that it gets deleted right away, just not during the life of the onCollision function call.
#19
08/14/2013 (7:12 pm)
I have added "%obj.schedule(500, "delete");" and the item gets deleted but I noticed the player gets more points. So when the item is spawned and the player instantly moves on it before the item is delete that player gets multiple points.

Also with commenting out
if (%col.client.score >= $Game::EndGameScore)  
         cycleGame();  
  
         return;
The game doesn't end when the score is reached.
#20
08/14/2013 (8:02 pm)
Try setting the schedule time to zero. Also, you could set a flag like %obj.used = 1; at the same time you schedule. Then and (&&) that in your if statement so you don't get multiple scores if the zero time does not solve this. Remember the schedule will not run until after you leave the function even if the time is zero.

Edit:
I mean && !%obj.used to the if statement.
Page «Previous 1 2