GUIs: Notify Icon
The Repair Drone Notify Icon
Adding a new notify icon to the HUD.
The Strogg constructor class has an upgrade that allows them to send out a flying repair drone to repair deployables and vehicles. What you have to be careful about while the repair drone is out is to not go too far away or it will stop repairing and try to return to you.
In this tutorial we will be adding a new notify icon that will display the distance between the player and the repair drone. This is useful for knowing how far away from the repair drone you can go before it tries to return to you.
Notify icon bar:
Where to Start
The repair drone has been implemented in the script/tools/repair_drone.script script, this is where we should update the GUIs with the distance to the player.
The notify icons are all found in guis/game/hud/hud.gui. We also need to add a global property which is updated from the script and used by the guis, the global properties is found in guis/globals.gui.
Game Script
First let's set up the game script to update a GUI property with the distance to the player in percent, where 0 is at the player position and a value of 1 is the maximum distance before the repair drone has to return.
We find two kind of objects in the repair_drone.script:
- tool_repair_drone - The script for the repair drone tool the player is holding in his hand, this is not the script we want to work on.
- repair_drone - This is the object we need to modify.
When the GUI properties need to be updated from the scripts it is often done in a function called UpdateGUI. There is none for the repair_drone object so we add this function. UpdateGUI needs to be called regularly while the repair drone is out. The repair drone has three different states (seeking/repairing/returning) and hence three different while loops we have to add calls to UpdateGUI. The calls are added at the end of the while loops:
repair_drone::SeekTarget:
DoMove( desiredOrigin ); UpdateGUI(); sys.waitFrame(); }
repair_drone::RepairTarget:
UpdateGUI(); sys.waitFrame(); }
repair_drone::Return:
DoMove( newOrigin ); UpdateGUI(); sys.waitFrame(); }
repair_drone::UpdateGUI:
void repair_drone::UpdateGUI() { entity ownerEntity = getOwnerEntity(); // Only update the owner of the repair drone if ( ownerEntity == sys.getLocalPlayer() ) { // signal that the repair drone is active sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.repairDroneActive", 1.0f ); // repairDroneRange is set to the distance in percent to the player sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.repairDroneRange", OwnerReturnDistancePct( ownerEntity ) ); } }
The distance to the player is a percentage and is calculated in OnwerReturnDistancePct:
float repair_drone::OwnerReturnDistancePct( entity ownerEntity ) { // calculate distance to player float distance = sys.vecLength( getWorldOrigin() - ownerEntity.getWorldOrigin() ); // convert to percentage of max distance before it has to return float pct = distance / returnDistance; return pct; }
There is one small thing left, once the repair drone has been destroyed we need to set the repairDroneActive GUI property back to 0 to signal the GUIs to destroy the notify icon:
void repair_drone::destroy() { if ( cachedOwner == sys.getLocalPlayer() ) { sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.repairDroneActive", 0.0f ); } }
That's all that is needed for the game scripts.
GUI Script
First let's open guis/globals.gui and add the needed properties. They should be added to the gameHud namespace:
"repairDroneActive" "float" // repair drone active status "repairDroneRange" "float" // range between the repair drone and player in percent of max range
In guis/game/hud/hud.gui we need to cache the notify icon for the repair drone. We will use the same icon as for the repair drone in the weapon menu, but give it a repairdroneicon alias (line 114):
"teleporteritemicon" "guis/assets/icons/weapons/teleportgun" "repairdroneicon" "guis/assets/icons/weapons/repair_drone" "constructicon" "hud/icons/missionsystem/obj_build"
The global property gameHud.repairDroneActive we added should be initialized to 0, which we do in the HUD's onActivate event, line 320:
globals.gameHud.teleporterActive = 0; globals.gameHud.repairDroneActive = 0; globals.vehicles.siegeMode = floatToHandle( -1 );
All notify icon types have a unique number associated with them, we add a new one for the repair drone on line 1028:
#define DI_SUPPLIES2 8 #define DI_REPAIRDRONE 9
Now we need a handle to the icon which later can be used to draw the icon (line 1094):
// Teleporter Item handle teleporterItemMaterial = gui.cacheMaterial( "teleporterItemIcon", "_st teleporteritemicon" ); handle teleporterItemIcon; // Repair drone handle repairDroneMaterial = gui.cacheMaterial( "repairDroneIcon", "_st repairdroneicon" ); handle repairDroneIcon; // handle to the notify icon itself.
This is how the GUI can respond to any changes to the properties changed by the game code. We set up a onPropertyChanged for the gameHud.repairDroneActive property (line 1334):
onPropertyChanged "globals.gameHud.teleporterActive" { postNamedEvent( "updateTeleporter" ); } onPropertyChanged "globals.gameHud.repairDroneActive" { // post a named event and do the actual work in updateRepairDrone postNamedEvent( "updateRepairDrone" ); } onPropertyChanged "player.role" { ...
The actual creation/deletion of the repair drone notify icon happens in the named event updateRepairDrone (line 1282):
onNamedEvent "updateRepairDrone" { if( globals.gameHud.repairDroneActive ) { // the repair drone is active, see if the notify icon has already been created if( isValidHandle( repairDroneIcon ) == false ) { // create icon repairDroneIcon = addIcon( "nodraw" ); // set the lastItenAdded handle to the repair drone icon lastItemAdded = gui.copyHandle( repairDroneIcon ); // set DI_REPAIRDRONE for the icon, needed to identify the icon during drawing setItemData( repairDroneIcon, DI_REPAIRDRONE ); // set up the material to the repair drone icon repairDroneMaterial = gui.cacheMaterial( "repairDroneIcon", "_st repairdroneicon" ); // bump the icon, this moves the icon around to get the players attention bumpIcon( lastItemAdded, NOTIFY_BUMP_TABLE ); } } else { // see if notify icon handle is valid if( isValidHandle( repairDroneIcon ) ) { // it is valid, remove the icon removeIcon( repairDroneIcon ); // set to an invalid handle repairDroneIcon = floatToHandle( -1 ); } } } onPropertyChanged "globals.gameHud.supplyCrateHealth0" "globals.gameHud.supplyCrateSupplies0" { ...
We should also call the named event once at the creation of the GUI in addition to when the gameHud.repairDroneActive property changes (in onCreate, line 1108):
... postNamedEvent( "updateTeleporter" ); postNamedEvent( "updateRepairDrone" ); }
Now the final thing missing is the actual drawing of the repair drone icon and the range indicator. An empty notify icon will automatically be drawn, but we want to draw the repair drone icon and range indicator in addition, this is done in onPreDrawIcon (line 1410):
// Repair Drone if( itemData == DI_REPAIRDRONE ) { // we are about to draw the repair drone icon // set the rectangle of the repair drone icon we want to draw scratchRect.x = itemRect.x - 10,itemRect.y + 6, 64, 16; // Set the color we want when drawing scratchColor = COLOR_WEAPON_LIST_ICON_LINE; scratchColor.a = immediate( scratchColor.a ) * itemColor.a; // Draw the repair drone icon drawCachedMaterial( repairDroneMaterial, scratchRect, scratchColor ); // now draw the indicator below the repair drone icon with a white color scratchColor = COLOR_WHITE; scratchColor.a = immediate( scratchColor.a ) * itemColor.a; // x and width of the rectangle depends on the distance to the repair drone scratchRect.x = itemRect.x + 2 + ( ( 1.0 - globals.gameHud.repairDroneRange ) * 42 ); scratchRect.y = itemRect.y + 28; scratchRect.w = 42 * ( globals.gameHud.repairDroneRange ); scratchRect.h = 10; // draw the range indicator now clipToRect( scratchRect ); drawCachedMaterial( progress, "itemRect.x + 2, itemRect.y + 28, 42, 10", scratchColor ); unclipRect(); return; }
That's it! Here's how it looks like in-game: