diff --git a/rsrc/aftershock/img/atlas.png b/rsrc/aftershock/img/atlas.png index bcb36ee1..afa98bf4 100644 Binary files a/rsrc/aftershock/img/atlas.png and b/rsrc/aftershock/img/atlas.png differ diff --git a/rsrc/img/atlas.png b/rsrc/img/atlas.png index bcb36ee1..afa98bf4 100644 Binary files a/rsrc/img/atlas.png and b/rsrc/img/atlas.png differ diff --git a/src/assets/AssetManager.cpp b/src/assets/AssetManager.cpp index 11867f13..177d03bd 100644 --- a/src/assets/AssetManager.cpp +++ b/src/assets/AssetManager.cpp @@ -322,6 +322,12 @@ std::string AssetManager::GetOggPath(MaybePackage package, int16_t id) return GetFullPath(package, relativePath.str()); } +std::string AssetManager::GetImagePath(MaybePackage package, std::string fileName) { + std::stringstream relativePath; + relativePath << "img" << PATHSEP << fileName; + return GetFullPath(package, relativePath.str()); +} + void AssetManager::LoadEnumeratedObjectTypes() { std::stringstream path; diff --git a/src/assets/AssetManager.h b/src/assets/AssetManager.h index 54c8169a..fb0b9ff4 100644 --- a/src/assets/AssetManager.h +++ b/src/assets/AssetManager.h @@ -142,6 +142,14 @@ class AssetManager { */ static std::optional> GetHull(int16_t id); + /** + * Get the image with the provided fileName, if available. + * + * @param fileName The name of the file. + * @return the full file path of the image + */ + static std::string GetImagePath(MaybePackage package, std::string fileName); + /** * Run important operations at application start. */ diff --git a/src/game/CAbstractPlayer.cpp b/src/game/CAbstractPlayer.cpp index 62091fed..34a438fa 100644 --- a/src/game/CAbstractPlayer.cpp +++ b/src/game/CAbstractPlayer.cpp @@ -997,12 +997,6 @@ void CAbstractPlayer::SetFreeCamState(Boolean state) { itsGame->ToggleFreeCam(freeView); itsFreeCam->ToggleState(freeView); - - if (freeView) { - SDL_Log("Free cam toggled on!"); - } - else - SDL_Log("Free cam toggled off!"); } Boolean CAbstractPlayer::IsFreeCamAttached() { diff --git a/src/game/CAvaraApp.cpp b/src/game/CAvaraApp.cpp index dc45b248..1d27944b 100755 --- a/src/game/CAvaraApp.cpp +++ b/src/game/CAvaraApp.cpp @@ -440,6 +440,9 @@ void CAvaraAppImpl::ParamLine(short index, MsgAlignment align, StringPtr param1, case kmAKilledBPlayer: buffa << a << " killed " << b << "."; break; + case kmKilledByCollision: + buffa << a << " was killed by the world."; + break; case kmUnavailableNote: buffa << a << " is busy."; category = MsgCategory::Error; diff --git a/src/game/CHUD.cpp b/src/game/CHUD.cpp index d38e11fc..d3f7b689 100644 --- a/src/game/CHUD.cpp +++ b/src/game/CHUD.cpp @@ -1,4 +1,5 @@ #include "CHUD.h" +#include "AssetManager.h" #include "AbstractRenderer.h" #include "CAbstractPlayer.h" #include "CAvaraGame.h" @@ -27,7 +28,8 @@ bool sortByScore(std::pair i, std::pair& thePlayers, int chudHeight, NVGcontext *ctx) { @@ -735,10 +737,15 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa // Event player names std::string killerName = " " + event.player; std::string killedName = " " + event.playerTarget; - float teamColorRGB[3], teamTargetColorRGB[3]; + float teamColorRGB[3], teamTargetColorRGB[3], iconLeftMargin = 23.0f; // Get how wide the event rect needs to be std::string eventText = killerName + " " + killedName; + if (event.weaponUsed == ksiObjectCollision) { + eventText = " " + killedName; + killerName = ""; + iconLeftMargin = 11.0f; + } nvgBeginPath(ctx); nvgTextAlign(ctx, NVG_ALIGN_RIGHT); nvgFontSize(ctx, fontSize); @@ -749,7 +756,7 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa // Get Measurements based on text size for the total size of the event box killEventSize[0] = killEventBounds[2] - killEventBounds[0] + 20.0f; killEventSize[1] = killEventBounds[3] - killEventBounds[1] + 10.0f; - killEventIconXPosition = killEventKillerNameBounds[2] - killEventKillerNameBounds[0] + 23.0f; // Position the icon in the empty space + killEventIconXPosition = killEventKillerNameBounds[2] - killEventKillerNameBounds[0] + iconLeftMargin; // Position the icon in the empty space eventPositionY = killEventPosition[1] + ((float)eventCount * (killEventSize[1] + 10.0f)); // Background box @@ -781,10 +788,10 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa iHeight = 51.0; break; case ksiObjectCollision: - ix = 0.0; + ix = 173.0; iy = 0.0; - iWidth = 0.0; - iHeight = 0.0; + iWidth = 58.0; + iHeight = 51.0; break; default: ix = 0.0; @@ -799,19 +806,25 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa longTeamTargetColor.ExportGLFloats(teamTargetColorRGB, 3); float teamTargetColorPosition = killEventPosition[0] - killEventSize[0] + killEventIconXPosition + imgWidth + 15.0f; - nvgBeginPath(ctx); - nvgRect(ctx, killEventPosition[0] - killEventSize[0] + 10.0f, eventPositionY + 10.0f, 9.0, killEventSize[1] - 20.0f); - nvgFillColor(ctx, nvgRGBAf(teamColorRGB[0], teamColorRGB[1], teamColorRGB[2], 1.0)); - nvgFill(ctx); + // Team color of killer + if (event.weaponUsed != ksiObjectCollision) { + nvgBeginPath(ctx); + nvgRect(ctx, killEventPosition[0] - killEventSize[0] + 10.0f, eventPositionY + 10.0f, 9.0, killEventSize[1] - 20.0f); + nvgFillColor(ctx, nvgRGBAf(teamColorRGB[0], teamColorRGB[1], teamColorRGB[2], 1.0)); + nvgFill(ctx); + } + // Team color of killed nvgBeginPath(ctx); nvgRect(ctx, teamTargetColorPosition, eventPositionY + 10.0f, 9.0, killEventSize[1] - 20.0f); nvgFillColor(ctx, nvgRGBAf(teamTargetColorRGB[0], teamTargetColorRGB[1], teamTargetColorRGB[2], 1.0)); nvgFill(ctx); + // Draw icon for death reason DrawImage(ctx, images, 1.0, ix, iy, iWidth, iHeight, killEventPosition[0] - killEventSize[0] + killEventIconXPosition, eventPositionY + 5.0f, imgWidth, killEventSize[1] - 10.0f); + // Draw display text for event nvgBeginPath(ctx); nvgTextAlign(ctx, NVG_ALIGN_LEFT); nvgFontSize(ctx, fontSize); @@ -822,57 +835,21 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa break; } - case ksiScoreGoal: { + case ksiScoreGoal: + case ksiGrabBall: { // Event player names std::string playerName = " " + event.player; float teamColorRGB[3]; + std::string eventText; + if (event.scoreType == ksiScoreGoal) { + eventText = playerName + " scored!"; + } else if (event.scoreType == ksiGrabBall) { + eventText = playerName + " has the ball!"; + } else { + eventText = ""; + } // Get how wide the event rect needs to be - std::string eventText = playerName + " scored!"; - nvgBeginPath(ctx); - nvgTextAlign(ctx, NVG_ALIGN_RIGHT); - nvgFontSize(ctx, fontSize); - nvgFillColor(ctx, nvgRGBA(255, 255, 255, 255)); - nvgTextBounds(ctx, 0, 0, eventText.c_str(), NULL, killEventBounds); // Size of the entire rendered text - - // Get Measurements based on text size for the total size of the event box - killEventSize[0] = killEventBounds[2] - killEventBounds[0] + 20.0f; - killEventSize[1] = killEventBounds[3] - killEventBounds[1] + 10.0f; - eventPositionY = killEventPosition[1] + ((float)eventCount * (killEventSize[1] + 10.0f)); - - // Background box - DrawShadowBox(ctx, killEventPosition[0] - killEventSize[0], eventPositionY, killEventSize[0], killEventSize[1]); - nvgBeginPath(ctx); - nvgRoundedRect(ctx, killEventPosition[0] - killEventSize[0], eventPositionY, killEventSize[0], killEventSize[1], 4.0); - nvgFillColor(ctx, BACKGROUND_COLOR); - nvgFill(ctx); - - ARGBColor longTeamColor = *ColorManager::getTeamColor(event.team); - longTeamColor.ExportGLFloats(teamColorRGB, 3); - - nvgBeginPath(ctx); - nvgRect(ctx, killEventPosition[0] - killEventSize[0] + 10.0f, eventPositionY + 10.0f, 9.0, killEventSize[1] - 20.0f); - nvgFillColor(ctx, nvgRGBAf(teamColorRGB[0], teamColorRGB[1], teamColorRGB[2], 1.0)); - nvgFill(ctx); - - nvgBeginPath(ctx); - nvgTextAlign(ctx, NVG_ALIGN_LEFT); - nvgFontSize(ctx, fontSize); - nvgFillColor(ctx, nvgRGBA(255, 255, 255, 255)); - nvgText(ctx, killEventPosition[0] - killEventSize[0] + 10.0f, eventPositionY + 25.0f, eventText.c_str(), NULL); - - eventCount++; - break; - } - - case ksiGrabBall: - { - // Event player names - std::string playerName = " " + event.player; - float teamColorRGB[3]; - - // Get how wide the event rect needs to be - std::string eventText = playerName + " has the ball!"; nvgBeginPath(ctx); nvgTextAlign(ctx, NVG_ALIGN_RIGHT); nvgFontSize(ctx, fontSize); @@ -894,11 +871,13 @@ void CHUD::DrawKillFeed(NVGcontext *ctx, CNetManager *net, int bufferWidth, floa ARGBColor longTeamColor = *ColorManager::getTeamColor(event.team); longTeamColor.ExportGLFloats(teamColorRGB, 3); + // Draw player's team color nvgBeginPath(ctx); nvgRect(ctx, killEventPosition[0] - killEventSize[0] + 10.0f, eventPositionY + 10.0f, 9.0, killEventSize[1] - 20.0f); nvgFillColor(ctx, nvgRGBAf(teamColorRGB[0], teamColorRGB[1], teamColorRGB[2], 1.0)); nvgFill(ctx); + // Draw event text nvgBeginPath(ctx); nvgTextAlign(ctx, NVG_ALIGN_LEFT); nvgFontSize(ctx, fontSize); diff --git a/src/game/CScoreKeeper.cpp b/src/game/CScoreKeeper.cpp index a05611cd..d85140e0 100644 --- a/src/game/CScoreKeeper.cpp +++ b/src/game/CScoreKeeper.cpp @@ -222,27 +222,45 @@ void CScoreKeeper::Score(ScoreInterfaceReasons reason, event.teamTarget = hitTeam; event.damage = points; + SDL_Log("CAvaraGame::Obj Collision: player:%lu, team:%lu, hit:%lu, hitTeam:%lu, weapon: %d, reason:%lu\n", iface.playerID, iface.playerTeam, hitPlayer, iface.scoreTeam, itsGame->killReason, iface.scoreReason); + if (player >= 0 && player <= kMaxAvaraPlayers) { iface.playerName = itsGame->itsNet->playerTable[player]->PlayerName(); - if (reason == ksiKillBonus && hitPlayer >= 0 && hitPlayer <= kMaxAvaraPlayers) { - Str255 destStr; + Str255 destStr; + if (reason == ksiKillBonus && hitPlayer >= 0 && hitPlayer <= kMaxAvaraPlayers) { + // Player killed a player localScores.player[hitPlayer].lives--; if (hitTeam != team) { localScores.player[player].kills++; } if (!itsGame->itsApp->Get(kHUDShowKillFeed)) { + iface.consoleLine = destStr; + iface.consoleJustify = static_cast(MsgAlignment::Center); itsGame->itsApp->ComposeParamLine( destStr, kmAKilledBPlayer, iface.playerName, itsGame->itsNet->playerTable[hitPlayer]->PlayerName()); } + SDL_Log("CAvaraGame::Kill Event: player:%lu, team:%lu, hit:%lu, hitTeam:%lu, weapon: %d, reason:%lu\n", iface.playerID, iface.playerTeam, iface.scoreID, iface.scoreTeam, event.weaponUsed, iface.scoreReason); event.scoreType = ksiKillBonus; event.weaponUsed = itsGame->killReason; itsGame->AddScoreNotify(event); - SDL_Log("CAvaraGame::Kill Event: player:%lu, team:%lu, hit:%lu, hitTeam:%lu, weapon: %d, reason:%lu\n", iface.playerID, iface.playerTeam, iface.scoreID, iface.scoreTeam, event.weaponUsed, iface.scoreReason); - iface.consoleLine = destStr; - iface.consoleJustify = static_cast(MsgAlignment::Center); + } else if (reason == ksiKillBonus && itsGame->killReason == ksiObjectCollision) { + // Something other than a player did the killing blow + event.playerTarget = event.player; + event.teamTarget = event.team; + + if (!itsGame->itsApp->Get(kHUDShowKillFeed)) { + iface.consoleLine = destStr; + iface.consoleJustify = static_cast(MsgAlignment::Center); + itsGame->itsApp->ComposeParamLine( + destStr, kmKilledByCollision, itsGame->itsNet->playerTable[hitPlayer]->PlayerName(), NULL); + } + + event.scoreType = ksiKillBonus; + event.weaponUsed = itsGame->killReason; + itsGame->AddScoreNotify(event); } } else { iface.playerName = NULL; diff --git a/src/game/InfoMessages.h b/src/game/InfoMessages.h index 01cb8052..974f7833 100644 --- a/src/game/InfoMessages.h +++ b/src/game/InfoMessages.h @@ -28,6 +28,7 @@ enum { kmNewLatency2, kmWaitingForPlayer, kmAKilledBPlayer, + kmKilledByCollision, kmFragmentAlert, kmUnavailableNote, kmStartFailure,