Tactics-Action Hybrid Game Tutorial Part6: Fix Gui Calls
by Steve Acaster · 05/08/2011 (2:11 pm) · 2 comments
Back to Part Five: Energy and Turns
So, we've got all the basic functionality for our playerObject, and now he needs some team members. Before we start on that though, there are a few things regarding the server->client->HUD in stock T3D that needs to be changed. Stock T3D is set up with many clients on different computers in mind, connecting to a main server. Having many "playerObjects" on the same computer will cause the Client's HUD to update anytime an object of the Player or Aiplayer Class requires to update a parameter.
eg: Client shoots an Ai, Ai updates health, Client's own healthHUD GUI is updated, Ai throws ammo, Client's own WeaponHUD AmmoCounter decreases. We're going to stop that and make certain that the only changes to the Client's Head-Up-Display happen with the playerObject directly under his control.
Open up scripts/server/player.cs and make the following alterations:
Now, if a new playerObject is spawned which is not directly under our Client's control, the on-screen Energy and Health HUD will not update.
Now to sort out the calls to update the weaponHUD. Open scripts/server/weapon.cs and alter the following:
As you might have noticed %obj.client (playerObject's client) will not return anything because we are not controlling the object directly, so we have to make sure the localClientConnection is used.
Now in scripts/server/commands.cs let's finish up the new WeaponImage::UpdateWeaponHud function by adding to our custom serverCmdTurnOver function.
In scripts/client/client.cs alter the following:
That will stop the Healthhud and WeaponHud from vanishing at certain times and instead they will display empty or at zero.
Now we need to change the way items are dealt with when a playerObject is killed and drops them. In the stock game type they disappear quite quickly, but in this slower paced, turnedbased, tactics/action hybrid you really want them to stay - stay but not respawn after use. In scripts/server/item.cs alter:
Next, in scripts/server/health.cs edit;
Now weapons, ammo and health packs will continue to lie around in game after they have been thrown. Thrown items will not attempt to respawn once they have been picked up.
Whilst we are editing things, let's change the welcome message in scripts/server/gameCore.cs. This is not important and just for fun.
Now we should have a working logic environment that will not start altering the Client's on-screen GUI values unless it pertains to the playerObject under immediate control. So now we can create our multiple team members, teams, and a specific gameType; "TorqueTactics".
Part Seven: Tactics GameType
So, we've got all the basic functionality for our playerObject, and now he needs some team members. Before we start on that though, there are a few things regarding the server->client->HUD in stock T3D that needs to be changed. Stock T3D is set up with many clients on different computers in mind, connecting to a main server. Having many "playerObjects" on the same computer will cause the Client's HUD to update anytime an object of the Player or Aiplayer Class requires to update a parameter.
eg: Client shoots an Ai, Ai updates health, Client's own healthHUD GUI is updated, Ai throws ammo, Client's own WeaponHUD AmmoCounter decreases. We're going to stop that and make certain that the only changes to the Client's Head-Up-Display happen with the playerObject directly under his control.
Open up scripts/server/player.cs and make the following alterations:
function Armor::onAdd(%this, %obj)
{
// Vehicle timeout
%obj.mountVehicle = true;
// Default dynamic armor stats
%obj.setRechargeRate(0);//(%this.rechargeRate);//yorks out to prevent auto recharging
%obj.setRepairRate(0);
// Set the numerical Health HUD
//%obj.updateHealth();
// Calling updateHealth() must be delayed now... for some reason
// %obj.schedule(50, "updateHealth");//yorks - remember this, we'll disable it later <--- DISABLE NOW!
%obj.schedule(50, "restoreEnergy");//yorks
}
//...
function Armor::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
//...
// Update the numerical Health HUD
if(localClientConnection.player == %obj)//yorks in
%obj.updateHealth();
//...
}
//...
function Armor::onDisabled(%this, %obj, %state)
{
//...
//yorks add at the bottom
if(localClientConnection.player == %obj)
{
%obj.setEnergyLevel(0);
%obj.updateEnergy();
}
%obj.setShapeName("");
}
//...
function Player::updateHealth(%player)
{
//...
//this fixes an issue with how healthpacks work on a schedule
//so it only displays the changes on the healed playerObject when you switch team members
if(%player == localClientConnection.player)//<------ yorks insert this here!
commandToClient(localClientConnection, 'setNumericalHealthHUD', %curHealth);//<--changed yorks
}
//...
function Player::updateEnergy(%player)
{
//...
if(%player == localClientConnection.player)//<---- yorks add
commandToClient(localClientConnection, 'setNumericalEnergyHUD', %curEnergy);
}
//...
function Player::restoreEnergy(%player)
{
%maxEnergy = %player.getDatablock().maxEnergy;
%player.setEnergyLevel(%maxEnergy);
if(%player == localClientConnection.player)//<------ yorks insert this here!
commandToClient(localClientConnection, 'setNumericalEnergyHUD', %maxEnergy);
}
//...Now, if a new playerObject is spawned which is not directly under our Client's control, the on-screen Energy and Health HUD will not update.
Now to sort out the calls to update the weaponHUD. Open scripts/server/weapon.cs and alter the following:
function WeaponImage::onMount(%this, %obj, %slot)
{
// Images assume a false ammo state on load. We need to
// set the state according to the current inventory.
if(%this.ammo !$= "")
{
if (%obj.getInventory(%this.ammo))
{
%obj.setImageAmmo(%slot, true);
%currentAmmo = %obj.getInventory(%this.ammo);
}
else
%currentAmmo = 0;
//yorks - changes below
// %obj.client.RefreshWeaponHud(%currentAmmo, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle);
if(localClientConnection.player == %obj)
commandToClient(localClientConnection, 'RefreshWeaponHud', %currentAmmo, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle);
//yorks changes end
}
}
//yorks - whole new function to add here!
function WeaponImage::UpdateWeaponHud(%this, %obj, %slot)
{
if(%this.ammo !$= "")
{
if (%obj.getInventory(%this.ammo))
{
%obj.setImageAmmo(%slot, true);
%currentAmmo = %obj.getInventory(%this.ammo);
}
else
%currentAmmo = 0;
commandToClient(localClientConnection, 'RefreshWeaponHud', %currentAmmo, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle);
}
}
function WeaponImage::onUnmount(%this, %obj, %slot)
{
//yorks - replace everything inside this function with this
if(localClientConnection.player == %obj)
commandToClient(localClientConnection, 'RefreshWeaponHud', %currentAmmo, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle);
}
//...
function Ammo::onInventory(%this, %obj, %amount)
{
// The ammo inventory state has changed, we need to update any
// mounted images using this ammo to reflect the new state.
for (%i = 0; %i < 8; %i++)
{
if ((%image = %obj.getMountedImage(%i)) > 0)
if (isObject(%image.ammo) && %image.ammo.getId() == %this.getId())
{
%obj.setImageAmmo(%i, %amount != 0);
%currentAmmo = %obj.getInventory(%this);
// %obj.client.setAmmoAmountHud(%currentAmmo);//yorks out
//yorks add these 2 lines below
if(localClientConnection.player == %obj)
commandToClient(localclientconnection, 'SetAmmoAmountHud', %currentAmmo);
}
}
}As you might have noticed %obj.client (playerObject's client) will not return anything because we are not controlling the object directly, so we have to make sure the localClientConnection is used.
Now in scripts/server/commands.cs let's finish up the new WeaponImage::UpdateWeaponHud function by adding to our custom serverCmdTurnOver function.
function serverCmdTurnOver(%client)
{
//...
//yorks add to the bottom of the function
%wpn = %client.player.getmountedimage(%slot);
%wpn.UpdateWeaponHud(%client.player, %slot);
}In scripts/client/client.cs alter the following:
function clientCmdSetNumericalHealthHUD(%curHealth)
{
// Skip if the hud is missing.
if (!isObject(numericalHealthHUD))
return;
// The server has sent us our current health, display it on the HUD
numericalHealthHUD.setValue(%curHealth);
//yorks out - always display
/*
// Ensure the HUD is set to visible while we have health / are alive
if (%curHealth)
HealthHUD.setVisible(true);
else
HealthHUD.setVisible(false);
*/
}
//...
function clientCmdSetAmmoAmountHud(%amount)
{
//yorks replace whole function with this
AmmoAmount.setText("Ammo: "@%amount);
}
//...
function clientCmdRefreshWeaponHUD(%amount, %preview, %ret, %zoomRet)
{
//yorks start edit at top
// if (!%amount)
// AmmoAmount.setVisible(false);
// else
// {
// AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: "@ %amount);//yorks leave this!
// }
//yorks end edit, leave rest below as is
//...
}That will stop the Healthhud and WeaponHud from vanishing at certain times and instead they will display empty or at zero.
Now we need to change the way items are dealt with when a playerObject is killed and drops them. In the stock game type they disappear quite quickly, but in this slower paced, turnedbased, tactics/action hybrid you really want them to stay - stay but not respawn after use. In scripts/server/item.cs alter:
//yorks - replace this function
function Item::respawn(%this)
{
// This method is used to respawn static ammo and weapon items
// and is usually called when the item is picked up.
// Instant fade...
%this.startFade(0, 0, true);
%this.setHidden(true);
// Shedule a reapearance
if(%this.noRespawn == true)
{
%this.schedule($Item::RespawnTime, "delete");
}
else
{
%this.schedule($Item::RespawnTime, "setHidden", false);
%this.schedule($Item::RespawnTime + 100, "startFade", 1000, 0, false);
}
}
//...
function ItemData::onThrow(%this, %user, %amount)
{
//...
MissionGroup.add(%obj);
// %obj.schedulePop();//yorks out! we don't want thrown ammo to timeout
return %obj;
}Next, in scripts/server/health.cs edit;
function ShapeBase::tossPatch(%this)
{
//...
%item.static = false;
%item.noRespawn = 1;//yorks added!
MissionCleanup.add(%item);
//...
%item.setCollisionTimeout(%this);
//serverPlay3D(%item.getDataBlock().throwSound, %item.getTransform());
// %item.schedulePop();//yorks we don't want thrown health packs to timeout
return %item;
}Now weapons, ammo and health packs will continue to lie around in game after they have been thrown. Thrown items will not attempt to respawn once they have been picked up.
Whilst we are editing things, let's change the welcome message in scripts/server/gameCore.cs. This is not important and just for fun.
function GameConnection::onConnect(%client, %name)
{
//...
// Inform the client we've joined up
messageClient(%client,
'MsgClientJoin', '\c2Welcome to Torque Chronicles! The T3D Tactics/Action Hybrid Gameplay Tutorial.',// <--- yorks changed!
%client.playerName,
//...
}Now we should have a working logic environment that will not start altering the Client's on-screen GUI values unless it pertains to the playerObject under immediate control. So now we can create our multiple team members, teams, and a specific gameType; "TorqueTactics".
Part Seven: Tactics GameType
About the author
One Bloke ... In His Bedroom ... Making Indie Games ...
#2
The full thing is:
05/22/2011 (5:08 am)
Nope.The full thing is:
// Inform the client we've joined up
messageClient(%client,
'MsgClientJoin', '\c2Welcome to Torque Chronicles! The T3D Tactics/Action Hybrid Gameplay Tutorial.',// <--- yorks changed!
%client.playerName,
%client,
%client.sendGuid,
%client.score,
%client.kills,
%client.deaths,
%client.isAiControlled(),
%client.isAdmin,
%client.isSuperAdmin); 
Torque Owner Jeff Yaskus
jy games
// Inform the client we've joined up messageClient(%client, 'MsgClientJoin', 'c2Welcome to Torque Chronicles! The T3D Tactics/Action Hybrid Gameplay Tutorial.',// <--- yorks changed! %client.playerName);... the line had ended abruptly.