Author Topic: Spawning a bot next to you instead of at your exact position  (Read 1023 times)

What I need to do is spawn a bot alongside the player when they right click. GameFandan's CopyMod spawns them overtop of the player, like this:



What I need is for it to spawn BESIDE the player, like this:



What I have tried so far is below. This script spawns 3 bots at the origin of the map (0, 0, 0) whenever I right click instead of overtop of me, as it should be doing in its current state.(And I already asked GameFandan if I could use his code before doing this, so dont worry)

Code: [Select]
function FourLinkArmor::onTrigger(%this,%obj,%slot,%val)
{
Parent::onTrigger(%this,%obj,%slot,%val);

%postion = %obj.getTransform();

//All position values are set to zero until I can get the system itself working, so ignore that

//1st copy's position
%x1 = 0;
%y1 = 0;
%z1 = 0;
%mat1 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector1 = matrixAddVector(%mat1, %position);

//2nd copy's position
%x2 = 0;
%y2 = 0;
%z2 = 0;
%mat2 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector2 = matrixAddVector(%mat2, %position);

//3rd copy's position
%x3 = 0;
%y3 = 0;
%z3 = 0;
%mat3 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector3 = matrixAddVector(%mat3, %position);

if(isObject(%obj.client.bot))
{
%obj.client.bot.delete();
}
%bot1 = new AIplayer(%bot)
{
    datablock=PlayerStandardArmor; position = %vector1;
};
%bot2 = new AIplayer(%bot)
{
    datablock=PlayerStandardArmor; position = %vector2;
};
%bot3 = new AIplayer(%bot)
{
    datablock=PlayerStandardArmor; position = %vector3;
};

    MessageClient(%obj.client,0,"\c3You have cloned yourself.");
   
    $copyBots[$copyTotal] = %bot;
    $copyTotal++;
   
    %bot.isCopy = 1;
    %client.bot = %bot;
 
%rawr = %obj.client.player;
%obj.client.player = %bot;
%obj.client.applyBodyParts();
%obj.client.applyBodyColors();
%client.player = %rawr;
%bot1.setScale("1 1 1");
%bot1.setMoveObject(%obj.client.player);
%bot1.setShapeName(%obj.client.name);
%bot2.setScale("1 1 1");
%bot2.setMoveObject(%obj.client.player);
%bot2.setShapeName(%obj.client.name);
%bot3.setScale("1 1 1");
%bot3.setMoveObject(%obj.client.player);
%bot3.setShapeName(%obj.client.name);

}
The only thing Im getting from the console is "unable to find function matrixAddVector." If matrixAddVector  isnt the name of the function I'm looking for, then what is? (I need to add the x/y/z values to the corresponding values of the vector. I do know matrixMulVector is a function, but I dont want to multiply the two. How can I add them instead?)

Be merciful -- Im not that good, so what Im trying is probably stupid and way off from what I actually need. Help would, however, be greatly appreciated.

I hate slow boards. Bump.

%vectSum = vectorAdd(%vect1, %vect2);

%vectSum = vectorAdd(%vect1, %vect2);
But is a matrix a vector? :/

EDIT: Tried it anyways, console errors stopped but the bots are still spawning at the origin.

Also once I right click it becomes impossible to Self Delete, swap images, or drop the weapon, any clue as to why that is? When I press f7, I respawn and it leaves a duplicate client/player ._.

New code:
Code: [Select]
function FourLinkArmor::onTrigger(%this,%obj,%slot,%val)
{
Parent::onTrigger(%this,%obj,%slot,%val);
      if(%slot == 4 && %val)
      {
%postion = %obj.getTransform();

//All position values are set to zero until I can get the system itself working, so ignore that

//1st copy's position
%x1 = 0;
%y1 = 0;
%z1 = 0;
%mat1 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector1 = vectorAdd(%mat1, %position);
%bot1 = new AIplayer(%bot)
{
   datablock=PlayerStandardArmor; position = %vector1;
};

//2nd copy's position
%x2 = 0;
%y2 = 0;
%z2 = 0;
%mat2 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector2 = vectorAdd(%mat2, %position);
%bot2 = new AIplayer(%bot)
{
   datablock=PlayerStandardArmor; position = %vector2;
};

//3rd copy's position
%x3 = 0;
%y3 = 0;
%z3 = 0;
%mat3 = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector3 = vectorAdd(%mat3, %position);
%bot3 = new AIplayer(%bot)
{
   datablock=PlayerStandardArmor; position = %vector3;
};

//Don't think I need this VV

//if(isObject(%obj.client.bot))
//{
//%obj.client.bot.delete();
//}

     MessageClient(%obj.client,0,"\c3You have cloned yourself.");
    
     $copyBots[$copyTotal] = %bot;
     $copyTotal++;
    
     %bot.isCopy = 1;
   %client.bot = %bot;
  
%rawr = %obj.client.player;
%obj.client.player = %bot;
%obj.client.applyBodyParts();
%obj.client.applyBodyColors();
%client.player = %rawr;
%bot1.setScale("1 1 1");
%bot1.setMoveObject(%obj.client.player);
%bot1.setShapeName(%obj.client.name);
%bot2.setScale("1 1 1");
%bot2.setMoveObject(%obj.client.player);
%bot2.setShapeName(%obj.client.name);
%bot3.setScale("1 1 1");
%bot3.setMoveObject(%obj.client.player);
%bot3.setShapeName(%obj.client.name);
}
}
« Last Edit: July 08, 2011, 08:07:28 PM by takato14 »

Also once I right click it becomes impossible to Self Delete, swap images, or drop the weapon, any clue as to why that is? When I press f7, I respawn and it leaves a duplicate client/player ._.

Because of this:
Code: [Select]
%obj.client.player = %bot;You're setting %player to %bot, so whenever any function tries to access player, it uses %bot.
Also, I don't see anywhere where %bot is defined

But is a matrix a vector? :/
What in god's name are you doing in this code. Just get the player's position add like 5 units to the right.

What in god's name are you doing in this code. Just get the player's position add like 5 units to the right.

...and which way is "right", my good man?

Is it east, the X of a vector?
Is it north, the Y of a vector?
Or is it some combination of the two?


Edit:

Also, if you want to make a bot controllable by a client, you're going to have to do some hacky stuff no matter which route you take.

The first route is to set the client's player to the bot, which is what you're doing.
It requires you to package anything which you want to affect the original player.

The second route is calling GameConnection.setControlObje ct(AIPlayer);, which is the first method I tried.
It requires you to package anything which you want to affect the bot, like servercmdUseTool.
« Last Edit: July 09, 2011, 03:18:26 AM by Xalos »

Here's a little bit of code I whipped up that spawns a bot directly to the right of the player every time. You can also transfer CONTROL to the object. However, if you draw out a tool or something like that (anything that uses a server command instead of a trigger), the real player will do the action instead.

Code: (spawnBot.cs) [Select]
function servercmdSpawnBot(%cl)
{
   if(!isObject(%cl) || !isObject(%cl.player))
      return;
   %pi = 3.1415926;
   %pl = %cl.player;
   %vect = %pl.getForwardVector();
   %angle = mAtan(getWord(%vect, 0), getWord(%vect, 1));
   %angle += %pi/2;   //If you want to spawn the bot on the left side of the player, change this to %angle -= %pi/2;
   %vectX = mSin(%angle);
   %vectY = mCos(%angle);
   %scale = mSqrt(mPow(%vectX, 2) + mPow(%vectY, 2));
   %dist = 3;   //Change this to be however far away from the player you want
   %mod = %dist/%scale;
   %vectX *= %mod;
   %vectY *= %mod;
   %x = getWord(%pl.position, 0) + %vectX;
   %y = getWord(%pl.position, 1) + %vectY;
   %z = getWord(%pl.position, 2);
   %bot = new AIPlayer()
   {
      datablock = PlayerStandardArmor;
      position = %x SPC %y SPC %z;
      rotation = %pl.rotation;
   };
   %bot.setAimObject(%pl);
   %bot.setMoveObject(%pl);
   %bot.doMoveLoop(%cl);
   %bot.owner = %cl;
   %cl.bot[-1+%cl.bots++] = %bot;
   return %bot;
}
function AIPlayer::doMoveLoop(%bot, %cl)
{
   if(!isObject(%cl))
      return;
   %bot.schedule(50, "doMoveLoop", %cl);
   if(!isObject(%cl.player) || %cl.player.getState() $= "DEAD")
   {
      %bot.stop();
      %bot.setMoveX(0);
      %bot.setMoveY(0);
      %bot.setAimObject(0);
      %bot.setMoveObject(0);
      return;
   }
   %pl = %cl.player;
   %respectfulDist = 10;   //How far the bots follow you at.
   if(vectorDist(getWords(%bot.position, 0, 1) SPC 0, getWords(%pl.position, 0, 1) SPC 0) <= %respectfulDist)
   {
      %bot.stop();
      %bot.setMoveX(0);
      %bot.setMoveY(0);
      %bot.setAimObject(%pl);
   }
   else
   {
      %bot.setMoveX(0);
      %bot.setMoveY(10);
      %bot.setAimObject(%pl);
      %bot.setMoveObject(%pl);
   }
}

package spawnBot
{
   function Armor::onTrigger(%data, %obj, %trig, %tog)
   {
      if(%trig == 4 && %tog)
      {
         if(isObject(%obj.client) && %obj.client.bots > 0)
         {
            %eye1 = %obj.getEyePoint();
            %eye2 = vectorScale(vectorNormalize(%obj.getEyeVector()), 100);
            %ray = containerRaycast(%eye1, %eye2, $TypeMasks::FxBrickObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType, %obj);
            %hit = getWord(%ray, 0);
            if(isObject(%hit) && (%hit.getClassName() $= "AIPlayer" || %hit.getClassName() $= "Player"))
            {
               %obj.client.setControlObject(%hit);
               %hit.client = %obj.client;
               return;
            }
         }
      }
      Parent::onTrigger(%data, %obj, %trig, %tog);
   }
   function GameConnection::onClientLeaveGame(%cl)
   {
      for(%i=0;%i<%cl.bots;%i++)
         if(isObject(%cl.bot[%i]))
            %cl.bot[%i].delete();
      Parent::onClientLeaveGame(%cl);
   }
};
activatePackage(spawnBot);
« Last Edit: July 09, 2011, 04:28:29 AM by Xalos »

Look at GreekBots (made by Hephaestus) for how to control the bot. It had it down perfectly. I finally found a download for it.

Here's a little bit of code I whipped up that spawns a bot directly to the right of the player every time. You can also transfer CONTROL to the object. However, if you draw out a tool or something like that (anything that uses a server command instead of a trigger), the real player will do the action instead.

Code: (spawnBot.cs) [Select]
function servercmdSpawnBot(%cl)
{
   if(!isObject(%cl) || !isObject(%cl.player))
      return;
   %pi = 3.1415926;
   %pl = %cl.player;
   %vect = %pl.getForwardVector();
   %angle = mAtan(getWord(%vect, 0), getWord(%vect, 1));
   %angle += %pi/2;   //If you want to spawn the bot on the left side of the player, change this to %angle -= %pi/2;
   %vectX = mSin(%angle);
   %vectY = mCos(%angle);
   %scale = mSqrt(mPow(%vectX, 2) + mPow(%vectY, 2));
   %dist = 3;   //Change this to be however far away from the player you want
   %mod = %dist/%scale;
   %vectX *= %mod;
   %vectY *= %mod;
   %x = getWord(%pl.position, 0) + %vectX;
   %y = getWord(%pl.position, 1) + %vectY;
   %z = getWord(%pl.position, 2);
   %bot = new AIPlayer()
   {
      datablock = PlayerStandardArmor;
      position = %x SPC %y SPC %z;
      rotation = %pl.rotation;
   };
   %bot.setAimObject(%pl);
   %bot.setMoveObject(%pl);
   %bot.doMoveLoop(%cl);
   %bot.owner = %cl;
   %cl.bot[-1+%cl.bots++] = %bot;
   return %bot;
}
function AIPlayer::doMoveLoop(%bot, %cl)
{
   if(!isObject(%cl))
      return;
   %bot.schedule(50, "doMoveLoop", %cl);
   if(!isObject(%cl.player) || %cl.player.getState() $= "DEAD")
   {
      %bot.stop();
      %bot.setMoveX(0);
      %bot.setMoveY(0);
      %bot.setAimObject(0);
      %bot.setMoveObject(0);
      return;
   }
   %pl = %cl.player;
   %respectfulDist = 10;   //How far the bots follow you at.
   if(vectorDist(getWords(%bot.position, 0, 1) SPC 0, getWords(%pl.position, 0, 1) SPC 0) <= %respectfulDist)
   {
      %bot.stop();
      %bot.setMoveX(0);
      %bot.setMoveY(0);
      %bot.setAimObject(%pl);
   }
   else
   {
      %bot.setMoveX(0);
      %bot.setMoveY(10);
      %bot.setAimObject(%pl);
      %bot.setMoveObject(%pl);
   }
}

package spawnBot
{
   function Armor::onTrigger(%data, %obj, %trig, %tog)
   {
      if(%trig == 4 && %tog)
      {
         if(isObject(%obj.client) && %obj.client.bots > 0)
         {
            %eye1 = %obj.getEyePoint();
            %eye2 = vectorScale(vectorNormalize(%obj.getEyeVector()), 100);
            %ray = containerRaycast(%eye1, %eye2, $TypeMasks::FxBrickObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType, %obj);
            %hit = getWord(%ray, 0);
            if(isObject(%hit) && (%hit.getClassName() $= "AIPlayer" || %hit.getClassName() $= "Player"))
            {
               %obj.client.setControlObject(%hit);
               %hit.client = %obj.client;
               return;
            }
         }
      }
      Parent::onTrigger(%data, %obj, %trig, %tog);
   }
   function GameConnection::onClientLeaveGame(%cl)
   {
      for(%i=0;%i<%cl.bots;%i++)
         if(isObject(%cl.bot[%i]))
            %cl.bot[%i].delete();
      Parent::onClientLeaveGame(%cl);
   }
};
activatePackage(spawnBot);
This could be helpful. Thanks.