Skip to content

Commit

Permalink
Allow pairing grenades (for network games with dedicated servers)
Browse files Browse the repository at this point in the history
Grenades can be paired, even before a game starts. If you score an
elimination of an enemy with a paired grenade, you will get credit
for the elimination. Friendly fire from grenades will still hurt
yourself and your teammates and you will not get credit for any
friendly eliminations from grenades.

You will no longer receive damage from grenades during the pairing
or the disarm messages that a grenade sends.

Note, grenades select a random pairing ID and there are only 15
possible IDs. Try to pair grenades just before you use them to
avoid someone else taking your random pairing ID. Also try not to
pair a grenade while standing close to other players as they may
take your pairing.
  • Loading branch information
Dees-Troy committed Aug 2, 2018
1 parent 1d5a4f7 commit 6457506
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 43 deletions.
146 changes: 103 additions & 43 deletions app/src/main/java/com/simplecoil/simplecoil/FullscreenActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ private class LastHitData {
private long mLastShotFired = 0; // to reduce shots fired message spam
private long mLastHitMessage = 0; // to reduce hit/out message spam

// Grenade stuff
private static final byte GRENADE_DAMAGE = (byte) 0x01;
private static final byte GRENADE_NEW_PAIR = (byte) 0x0E;
private static final byte GRENADE_PAIR_ID = (byte) 0x0F;
private static final byte GRENADE_DISARM = (byte) 0x0D;

/* We run a continuous handler in the background while the tagger is connected to monitor the
connection status. Simply put, we set connectionTestHandler to false every time the handler
runs. Every time we receive telemetry data, we set connectionTestHandler back to true. When
Expand Down Expand Up @@ -2066,58 +2072,110 @@ else if (averageBattery >= BATTERY_LEVEL_PISTOL_YELLOW)
// Only the right-most 3 bits make up the shot ID
byte shot_id1 = (byte)(data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x07);
byte shot_id2 = (byte)(data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x07);
/*Log.e(TAG, "Hit by " + hit_by_player1);
if (hit_by_player2 != 0) {
Log.e(TAG, "hitdata: " + hit_by_player1 + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xFF) + " " + hit_by_player2 + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0xFF));
//Log.e(TAG, "Hit by " + hit_by_player1);
/*if (hit_by_player2 != 0) {
Log.e(TAG, "hitdata: " + Integer.toHexString(hit_by_player1) + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xFF) + " " + Integer.toHexString(hit_by_player2) + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0xFF));
} else {
Log.e(TAG, "hitdata: " + hit_by_player1 + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xFF));
Log.e(TAG, "hitdata: " + Integer.toHexString(hit_by_player1) + " " + Integer.toHexString(data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xFF));
}*/
if (hit_by_player1 == Globals.GRENADE_PLAYER_ID && (data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x0F) != GRENADE_DAMAGE) {
if ((data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x0F) == GRENADE_PAIR_ID) {
// This is a grenade trying to pair
if (Globals.getInstance().mPairedGrenadeID == 0) {
Globals.getInstance().mPairedGrenadeID = (byte)((data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xF0) >> 4);
if (mUseNetwork && mTcpClient.isDedicatedServer())
mTcpClient.sendPlayerGrenade();
Toast.makeText(getApplicationContext(), getString(R.string.grenade_paired_toast), Toast.LENGTH_SHORT).show();
}
} else if ((data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x0F) == GRENADE_NEW_PAIR || (data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x0F) == GRENADE_DISARM) {
Globals.getInstance().mPairedGrenadeID = 0;
}
}
if (hit_by_player2 == Globals.GRENADE_PLAYER_ID && (data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x0F) != GRENADE_DAMAGE) {
if ((data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x0F) == GRENADE_PAIR_ID) {
// This is a grenade trying to pair
if (Globals.getInstance().mPairedGrenadeID == 0) {
Globals.getInstance().mPairedGrenadeID = (byte)((data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0xF0) >> 4);
if (mUseNetwork && mTcpClient.isDedicatedServer())
mTcpClient.sendPlayerGrenade();
Toast.makeText(getApplicationContext(), getString(R.string.grenade_paired_toast), Toast.LENGTH_SHORT).show();
}
} else if ((data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x0F) == GRENADE_NEW_PAIR || (data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x0F) == GRENADE_DISARM) {
Globals.getInstance().mPairedGrenadeID = 0;
}
}
if (Globals.getInstance().mGameState != Globals.GAME_STATE_NONE) {
if ((mLastHitData1.playerID == hit_by_player1 && mLastHitData1.shotID == shot_id1) || (mLastHitData2.playerID == hit_by_player1 && mLastHitData2.shotID == shot_id1)) {
//Log.e(TAG, "Hit by 1 is using same shot ID from a previous hit, filter!" + hit_by_player1 + " " + data[RECOIL_OFFSET_HIT_BY1_SHOTID]);
} else {
mHitsTaken++;
String hitsTaken = "" + mHitsTaken;
mHitsTakenTV.setText(hitsTaken);
healthRemoved = Globals.DAMAGE_PER_HIT;
if (mUseNetwork) {
hit_by_id = (byte) (hit_by_player1 >> 2);
//Log.d(TAG, "hit by 1 ID is " + hit_by_id);
if ((hit_by_player1 != Globals.GRENADE_PLAYER_ID) && Globals.getInstance().mGameMode != Globals.GAME_MODE_FFA && Globals.getInstance().calcNetworkTeam(hit_by_id) == mNetworkTeam) {
//Log.d(TAG, "friendly fire ignored");
healthRemoved = 0;
} else {
if (Globals.getInstance().mPlayerSettings.get(hit_by_id) != null)
healthRemoved = Globals.getInstance().mPlayerSettings.get(hit_by_id).damage;
if (mLastHitMessage < System.currentTimeMillis()) {
mLastHitMessage = System.currentTimeMillis() + HIT_ANIMATION_DURATION_MILLISECONDS;
if (mHealth + healthRemoved > 0)
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_HIT, hit_by_id);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_OUT, hit_by_id);
if (hit_by_player1 == Globals.GRENADE_PLAYER_ID && (data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0x0F) != GRENADE_DAMAGE) {
// Ignore non-damage events from grenades
} else {
mHitsTaken++;
String hitsTaken = "" + mHitsTaken;
mHitsTakenTV.setText(hitsTaken);
healthRemoved = Globals.DAMAGE_PER_HIT;
if (mUseNetwork) {
hit_by_id = (byte) (hit_by_player1 >> 2);
//Log.d(TAG, "hit by 1 ID is " + hit_by_id);
if ((hit_by_player1 != Globals.GRENADE_PLAYER_ID) && Globals.getInstance().mGameMode != Globals.GAME_MODE_FFA && Globals.getInstance().calcNetworkTeam(hit_by_id) == mNetworkTeam) {
//Log.d(TAG, "friendly fire ignored");
healthRemoved = 0;
} else {
if (hit_by_player1 == Globals.GRENADE_PLAYER_ID) {
int grenadeID = (data[RECOIL_OFFSET_HIT_BY1_SHOTID] & 0xF0) >> 4;
if (grenadeID != 0) {
Globals.getmGrenadePairingsSemaphore();
if (Globals.getInstance().mGrenadePairings[grenadeID] != Globals.INVALID_PLAYER_ID)
hit_by_id = (byte)Globals.getInstance().mGrenadePairings[grenadeID];
Globals.getInstance().mGrenadePairingsSemaphore.release();
}
}
if (Globals.getInstance().mPlayerSettings.get(hit_by_id) != null)
healthRemoved = Globals.getInstance().mPlayerSettings.get(hit_by_id).damage;
if (mLastHitMessage < System.currentTimeMillis()) {
mLastHitMessage = System.currentTimeMillis() + HIT_ANIMATION_DURATION_MILLISECONDS;
if (mHealth + healthRemoved > 0)
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_HIT, hit_by_id);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_OUT, hit_by_id);
}
}
}
}
}
if ((mLastHitData1.playerID == hit_by_player2 && mLastHitData1.shotID == shot_id2) || (mLastHitData2.playerID == hit_by_player2 && mLastHitData2.shotID == shot_id2)) {
//Log.e(TAG, "Hit by 2 is using same shot ID from a previous hit, filter!");
} else if (hit_by_player2 != 0 && mHealth + healthRemoved > 0) {
healthRemoved += Globals.DAMAGE_PER_HIT;
if (mUseNetwork) {
hit_by_id = (byte)(hit_by_player1 >> 2);
//Log.d(TAG, "hit by 2 ID is " + hit_by_id);
if ((hit_by_player2 != Globals.GRENADE_PLAYER_ID) && Globals.getInstance().mGameMode != Globals.GAME_MODE_FFA && Globals.getInstance().calcNetworkTeam(hit_by_id) == mNetworkTeam) {
//Log.d(TAG, "friendly fire ignored");
healthRemoved -= Globals.DAMAGE_PER_HIT;
} else {
if (Globals.getInstance().mPlayerSettings.get(hit_by_id) != null)
healthRemoved += Globals.getInstance().mPlayerSettings.get(hit_by_id).damage;
if (mLastHitMessage < System.currentTimeMillis()) {
mLastHitMessage = System.currentTimeMillis() + HIT_ANIMATION_DURATION_MILLISECONDS;
if (mHealth + healthRemoved > 0)
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_HIT, hit_by_id);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_OUT, hit_by_id);
if (hit_by_player2 == Globals.GRENADE_PLAYER_ID && (data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0x0F) != GRENADE_DAMAGE) {
// Ignore non-damage events from grenades
} else {
healthRemoved += Globals.DAMAGE_PER_HIT;
if (mUseNetwork) {
hit_by_id = (byte) (hit_by_player1 >> 2);
//Log.d(TAG, "hit by 2 ID is " + hit_by_id);
if ((hit_by_player2 != Globals.GRENADE_PLAYER_ID) && Globals.getInstance().mGameMode != Globals.GAME_MODE_FFA && Globals.getInstance().calcNetworkTeam(hit_by_id) == mNetworkTeam) {
//Log.d(TAG, "friendly fire ignored");
healthRemoved -= Globals.DAMAGE_PER_HIT;
} else {
if (hit_by_player2 == Globals.GRENADE_PLAYER_ID) {
int grenadeID = (data[RECOIL_OFFSET_HIT_BY2_SHOTID] & 0xF0) >> 4;
if (grenadeID != 0) {
Globals.getmGrenadePairingsSemaphore();
if (Globals.getInstance().mGrenadePairings[grenadeID] != Globals.INVALID_PLAYER_ID)
hit_by_id = (byte)Globals.getInstance().mGrenadePairings[grenadeID];
Globals.getInstance().mGrenadePairingsSemaphore.release();
}
}
if (Globals.getInstance().mPlayerSettings.get(hit_by_id) != null)
healthRemoved += Globals.getInstance().mPlayerSettings.get(hit_by_id).damage;
if (mLastHitMessage < System.currentTimeMillis()) {
mLastHitMessage = System.currentTimeMillis() + HIT_ANIMATION_DURATION_MILLISECONDS;
if (mHealth + healthRemoved > 0)
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_HIT, hit_by_id);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_OUT, hit_by_id);
}
}
}
}
Expand Down Expand Up @@ -2180,10 +2238,12 @@ public void run() {
eliminatedBy = Globals.getInstance().getPlayerName(hit_by_id);
startSpawn(eliminatedBy);
if (mUseNetwork) {
if (mTcpClient.isDedicatedServer())
mTcpClient.sendTCPMessage(TcpServer.TCPMESSAGE_PREFIX + TcpServer.TCPPREFIX_MESG + NetMsg.NETMSG_ELIMINATED + hit_by_id, true);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_ELIMINATED, hit_by_id);
if (hit_by_id != Globals.getInstance().mPlayerID && Globals.getInstance().calcNetworkTeam(hit_by_id) != Globals.getInstance().calcNetworkTeam(Globals.getInstance().mPlayerID)) {
if (mTcpClient.isDedicatedServer())
mTcpClient.sendTCPMessage(TcpServer.TCPMESSAGE_PREFIX + TcpServer.TCPPREFIX_MESG + NetMsg.NETMSG_ELIMINATED + hit_by_id, true);
else
mUDPListenerService.sendUDPMessage(NetMsg.NETMSG_ELIMINATED, hit_by_id);
}
if (mHasLivesLimit && mEliminationCount <= 0) {
if (mTcpClient.isDedicatedServer())
mTcpClient.sendTCPMessage(TcpServer.TCPMESSAGE_PREFIX + TcpServer.TCPPREFIX_MESG + NetMsg.NETMSG_LEAVE);
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/java/com/simplecoil/simplecoil/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,16 @@ public class Globals {
public volatile Map<Byte, GPSData> mGPSData;
public volatile Map<Byte, PlayerSettings> mPlayerSettings;

public static final int MAX_GRENADE_IDS = 16;
public volatile byte mPairedGrenadeID = 0;
public volatile int[] mGrenadePairings;

public Semaphore mIPTeamMapSemaphore;
public Semaphore mTeamIPMapSemaphore;
public Semaphore mTeamPlayerNameSemaphore;
public Semaphore mGPSDataSemaphore;
public Semaphore mPlayerSettingsSemaphore;
public Semaphore mGrenadePairingsSemaphore;
public volatile boolean mUseGPS = false;
public volatile boolean mOnlyServerSettings = false;

Expand All @@ -121,6 +126,8 @@ public static synchronized Globals getInstance(){
mInstance.mTeamPlayerNameSemaphore = new Semaphore(1);
mInstance.mGPSDataSemaphore = new Semaphore(1);
mInstance.mPlayerSettingsSemaphore = new Semaphore(1);
mInstance.mGrenadePairingsSemaphore = new Semaphore(1);
mInstance.mGrenadePairings = new int[MAX_GRENADE_IDS];
}
return mInstance;
}
Expand Down Expand Up @@ -266,6 +273,24 @@ public static void getmPlayerSettingsSemaphore() {
}
}

public static void getmGrenadePairingsSemaphore() {
try {
getInstance().mGrenadePairingsSemaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void ClearGrenadePairings(boolean getSemaphore) {
if (getSemaphore)
getmGrenadePairingsSemaphore();
for (int index = 0; index < MAX_GRENADE_IDS; index++) {
getInstance().mGrenadePairings[index] = Globals.INVALID_PLAYER_ID;
}
if (getSemaphore)
getInstance().mGrenadePairingsSemaphore.release();
}

public static class PlayerSettings {
int health = Globals.MAX_HEALTH;
byte shots = Globals.RELOAD_COUNT;
Expand Down
29 changes: 29 additions & 0 deletions app/src/main/java/com/simplecoil/simplecoil/TcpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ private void sendPlayerInfo(boolean rejoin) {
} catch (JSONException e) {
e.printStackTrace();
}
if (Globals.getInstance().mPairedGrenadeID != 0)
sendPlayerGrenade();
}

public void sendPlayerSettings() {
Expand All @@ -315,6 +317,18 @@ public void sendPlayerSettings() {
}
}

public void sendPlayerGrenade() {
try {
JSONObject playerGrenade = new JSONObject();
playerGrenade.put(TcpServer.JSON_PLAYERID, (int) Globals.getInstance().mPlayerID);
playerGrenade.put(TcpServer.JSON_PAIRED_GRENADE_ID, (int) Globals.getInstance().mPairedGrenadeID);
String message = TcpServer.TCPMESSAGE_PREFIX + TcpServer.TCPPREFIX_JSON + playerGrenade.toString();
sendTCPMessage(message);
} catch (JSONException e) {
e.printStackTrace();
}
}

public void stopTcpClient() {
if (mIsDedicatedServer)
sleep(75); // Make sure that the end game message gets sent before we close down the socket
Expand All @@ -341,8 +355,22 @@ private void parseGameInfo(String message) {
boolean gotGPSSemaphore = false;
boolean gotPlayerSemaphores = false;
boolean gotPlayerSettingsSemaphore = false;
boolean gotGrenadePairingsSemaphore = false;
try {
JSONObject game = new JSONObject(message);
if (game.has(TcpServer.JSON_GRENADE_PAIRINGS)) {
Globals.getmGrenadePairingsSemaphore();
gotGrenadePairingsSemaphore = true;
Globals.ClearGrenadePairings(false);
JSONArray grenadePairings = game.getJSONArray(TcpServer.JSON_GRENADE_PAIRINGS);
for (int x = 0; x < grenadePairings.length(); x++) {
JSONObject grenadePairing = grenadePairings.getJSONObject(x);
Globals.getInstance().mGrenadePairings[grenadePairing.getInt(TcpServer.JSON_PAIRED_GRENADE_ID)] = grenadePairing.getInt(TcpServer.JSON_PLAYERID);
}
gotGrenadePairingsSemaphore = false;
Globals.getInstance().mGrenadePairingsSemaphore.release();
return;
}
if (game.has(TcpServer.JSON_GPSUPDATE)) {
JSONArray updates = game.getJSONArray(TcpServer.JSON_GPSUPDATE);
Globals.getmGPSDataSemaphore();
Expand Down Expand Up @@ -516,6 +544,7 @@ private void parseGameInfo(String message) {
}
if (gotGPSSemaphore) Globals.getInstance().mGPSDataSemaphore.release();
if (gotPlayerSettingsSemaphore) Globals.getInstance().mPlayerSettingsSemaphore.release();
if (gotGrenadePairingsSemaphore) Globals.getInstance().mGrenadePairingsSemaphore.release();
}
}

Expand Down
Loading

0 comments on commit 6457506

Please sign in to comment.