This week I've been focusing on some of the fundamental code for the Capture the Flag game mode--getting combat mechanics working between players. It's important for players to be able to interact with one another, and this code (and the mechanics they entail) will be important to how people play and enjoy the game.

The main idea behind the PvP is that players can use a weapon to tag other players, causing them to drop their flag if it is being held.

To begin, I created a new weapon for the player to use, the magic staff.




Magic Staff texture vs in game

I set the magic staff to be given to the player when they teleport to their base by adding this line to the TeleporterSystem:

inventoryManager.giveItem(player, EntityRef.NULL, entityManager.create("LightAndShadowResources:magicStaff"));

since that is where they have chosen one of the warring factions and will be fighting with the other.

I then started in on the code that would let players interact with one another and potentially steal the flag from one another. What confused me in thinking about the system was that in some of the other onActivate code that I've written, the component for triggering the event is on the item the player is targeting when pressing Activate, rather than dependent on the object being held.

To that end, I altered the delta of the Player.prefab to have a component to look for on activate ("FlagDropOnActivate" : {}).

The AttackSystem works in the following way:

-Checks to see if the attacking player is holding a magic staff (or potentially any other item with the given component attached
if (attackingPlayer.getComponent(CharacterHeldItemComponent.class).selectedItem.hasComponent(RaycastOnActivateComponent.class)) {

-Checks to see if the thing being targeted on activate is a player with an inventory (should always be true for now)
if (entity.hasComponent(PlayerCharacterComponent.class) && entity.hasComponent(CharacterHeldItemComponent.class)) {

-Checks to see if the player being attacked is holding a red or black flag
if (heldItem.getComponent(BlockItemComponent.class).blockFamily.getURI().toString().equals(BLACK_FLAG_URI)
|| heldItem.getComponent(BlockItemComponent.class).blockFamily.getURI().toString().equals(RED_FLAG_URI)) {

-If so, make the attacked player drop the flag
entity.send(new DropItemRequest(heldItem, entity, impulseVector, newPosition));

So far, this works as intended--if the player is targeted by someone with the magic staff and the attackers activates the staff, the player holding the flag will drop it. It can then be picked up by either party. So it's a success!

However, there are still certain things that to be fixed up:
- Right now the player has to be holding the flag to be able to drop it, rather than just having it in their inventory. The way I was envisioning it, the player cannot use the magic staff while holding the flag (adding slightly more difficulty to being the flag bearer) but this can be changed to see if the person is holding a flag in general
- I need to fix the issue of players being able to pick up their own team's flag when it's in the world (my current plan is to have the flag sent back to spawn point/base on pickup)
-There is also the question of friendly fire--should a player be able to target a flagbearer from their own team and cause the flag to drop?
- cervator mentioned there were some issues with teleporting using the red teleporter, which seems to work locally but I should investigate this further
- cervator also stated that the scores right now are not synchronized in a connected client server, which I need to test and get working. cerv said:
score shows up OK looking if i'm on a server/client, but not on a connected normal client. Probably something authority system vs client system or replication stuffs
yep looks like `ScoreSystem` is Authority only, yet it directly maps to UI stuff. So that in theory would only happen if you're running a server/client
i want to say the ping system might be a good example of a logic system that runs on the authority, yet displays UI updates on all clients
and i know it works and was recently improved some in https://github.com/MovingBlocks/Terasology/pull/3329 (which i fixed further with part of #3379)
involves `ServerPingSystem`, `ClientPingSystem`, `OnlinePlayersOverlay` and some other stuff
- There are a couple places where Strings can be replaced by constants, for consistency's sake
- More multiplayer testing

PRs for this week:
Player vs Player Combat Mechanics: https://github.com/Terasology/LightAndShadow/pull/68
Adding magic staff item: https://github.com/Terasology/LightAndShadowResources/pull/26