Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 4 commits
  • 10 files changed
  • 0 commit comments
  • 2 contributors
Commits on Jan 29, 2012
@Cyp Cyp Update secondary order in UI before synchronisation.
Fixes confusion over whether orders were accepted or not.

Clicking patrol and circle in the UI now makes the next order a patrol or circle
order, even if clicking before the patrol and circle secondary orders are
synchronised. Although, patrol and circle really shouldn't be secondary orders,
in the first place. Previous behaviour was to just go to the destination without
patrolling or circling, on clicking and then giving the order fast when in laggy
games.
4b53782
@Cyp Cyp Make [Password required] [No Tanks] [No Cyborgs] [No VTOLs] display m…
…ore consistent.

Reported by Emdek.
1fc0576
@Zarel Zarel Remove CB functionality from WSS droids - it was causing several bugs.
(cherry picked from commit 5dc9817)

Fixes ticket:3057.
cbb6a05
@Cyp Cyp Skip dead objects when applying splash and incendary damage.
Fixes an assertion due to re-destroying dead structures.

Introduced in 4657de6.
1a08636
Showing with 169 additions and 20 deletions.
  1. +3 −3 src/droid.cpp
  2. +2 −0 src/droiddef.h
  3. +1 −0 src/game.cpp
  4. +1 −1 src/intorder.cpp
  5. +1 −0 src/multibot.cpp
  6. +20 −8 src/multiint.cpp
  7. +1 −0 src/multisync.cpp
  8. +129 −7 src/order.cpp
  9. +1 −1 src/order.h
  10. +10 −0 src/projectile.cpp
View
6 src/droid.cpp
@@ -286,6 +286,8 @@ DROID::DROID(uint32_t id, unsigned player)
, psGroup(NULL)
, psGrpNext(NULL)
, secondaryOrder(DSS_ARANGE_DEFAULT | DSS_REPLEV_NEVER | DSS_ALEV_ALWAYS | DSS_HALT_GUARD)
+ , secondaryOrderPending(DSS_ARANGE_DEFAULT | DSS_REPLEV_NEVER | DSS_ALEV_ALWAYS | DSS_HALT_GUARD)
+ , secondaryOrderPendingCount(0)
, action(DACTION_NONE)
, actionPos(0, 0)
, psCurAnim(NULL)
@@ -3359,9 +3361,7 @@ bool cbSensorDroid(DROID *psDroid)
if (asSensorStats[psDroid->asBits[COMP_SENSOR].nStat].type ==
VTOL_CB_SENSOR ||
asSensorStats[psDroid->asBits[COMP_SENSOR].nStat].type ==
- INDIRECT_CB_SENSOR ||
- asSensorStats[psDroid->asBits[COMP_SENSOR].nStat].type ==
- SUPER_SENSOR)
+ INDIRECT_CB_SENSOR)
{
return true;
}
View
2 src/droiddef.h
@@ -182,6 +182,8 @@ struct DROID : public BASE_OBJECT
// secondary order data
UDWORD secondaryOrder;
+ uint32_t secondaryOrderPending; ///< What the secondary order will be, after synchronisation.
+ int secondaryOrderPendingCount; ///< Number of pending secondary order changes.
/* Action data */
DROID_ACTION action;
View
1 src/game.cpp
@@ -4218,6 +4218,7 @@ static bool loadSaveDroid(const char *pFileName, DROID **ppsCurrentDroidLists)
psDroid->experience = ini.value("experience", 0).toInt();
psDroid->timeLastHit = ini.value("timeLastHit", UDWORD_MAX).toInt();
psDroid->secondaryOrder = ini.value("secondaryOrder", DSS_NONE).toInt();
+ psDroid->secondaryOrderPending = psDroid->secondaryOrder;
psDroid->action = (DROID_ACTION)ini.value("action", DACTION_NONE).toInt();
psDroid->actionPos = ini.vector2i("action/pos");
psDroid->actionStarted = ini.value("actionStarted", 0).toInt();
View
2 src/intorder.cpp
@@ -558,7 +558,7 @@ static SECONDARY_STATE GetSecondaryStates(SECONDARY_ORDER sec)
{
for (unsigned i = 0; i < SelectedDroids.size(); ++i)
{
- currState = secondaryGetState(SelectedDroids[i], sec);
+ currState = secondaryGetState(SelectedDroids[i], sec, ModeQueue);
if (bFirst)
{
state = currState;
View
1 src/multibot.cpp
@@ -446,6 +446,7 @@ bool recvDroid(NETQUEUE queue)
if (haveInitialOrders)
{
psDroid->secondaryOrder = initialOrders.secondaryOrder;
+ psDroid->secondaryOrderPending = psDroid->secondaryOrder;
orderDroidLoc(psDroid, DORDER_MOVE, initialOrders.moveToX, initialOrders.moveToY, ModeImmediate);
cbNewDroid(IdToStruct(initialOrders.factoryId, ANYPLAYER), psDroid);
}
View
28 src/multiint.cpp
@@ -928,18 +928,30 @@ static void addGames(void)
}
else
{
- if (NetPlay.games[i].limits)
+ std::string flags;
+ if (NetPlay.games[i].privateGame)
{
- ssprintf(tooltipbuffer[i], _("Hosted by %s, Game Status: %s%s%s%s!"), NetPlay.games[i].hostname,
- NetPlay.games[i].privateGame ? _("[Password required]") : "",
- NetPlay.games[i].limits & NO_TANKS ? _("[No Tanks]") : "",
- NetPlay.games[i].limits & NO_BORGS ? _(" [No Cyborgs]") : "",
- NetPlay.games[i].limits & NO_VTOLS ? _(" [No VTOLs]") : ""
- );
+ flags += " "; flags += _("[Password required]");
+ }
+ if (NetPlay.games[i].limits & NO_TANKS)
+ {
+ flags += " "; flags += _("[No Tanks]");
+ }
+ if (NetPlay.games[i].limits & NO_BORGS)
+ {
+ flags += " "; flags += _("[No Cyborgs]");
+ }
+ if (NetPlay.games[i].limits & NO_VTOLS)
+ {
+ flags += " "; flags += _("[No VTOLs]");
+ }
+ if (flags.empty())
+ {
+ ssprintf(tooltipbuffer[i], _("Hosted by %s"), NetPlay.games[i].hostname);
}
else
{
- ssprintf(tooltipbuffer[i], "Hosted by %s", NetPlay.games[i].hostname);
+ ssprintf(tooltipbuffer[i], _("Hosted by %s%s"), NetPlay.games[i].hostname, flags.c_str());
}
sButInit.pTip = tooltipbuffer[i];
}
View
1 src/multisync.cpp
@@ -438,6 +438,7 @@ bool recvDroidCheck(NETQUEUE queue)
MERGECOPYSYNC(pD->secondaryOrder, secondaryOrder, "u"); // The old code set this after changing orders, so doing that in case.
#undef MERGECOPYSYNC
#undef MERGEDELTA
+ pD->secondaryOrderPending = pD->secondaryOrder; // These droid checks are useless. TODO Completely remove recvDroidCheck and related code, since it's useless for synch, anyway?
syncDebugDroid(pD, '>');
View
136 src/order.cpp
@@ -2453,12 +2453,12 @@ DROID_ORDER chooseOrderLoc(DROID *psDroid, UDWORD x,UDWORD y, bool altOrder)
order = DORDER_DISEMBARK;
}
}
- else if (secondaryGetState(psDroid, DSO_CIRCLE) == DSS_CIRCLE_SET)
+ else if (secondaryGetState(psDroid, DSO_CIRCLE, ModeQueue) == DSS_CIRCLE_SET) // ModeQueue here means to check whether we pressed the circle button, whether or not it synched yet. The reason for this weirdness is that a circle order makes no sense as a secondary state in the first place (the circle button _should_ have been only in the UI, not in the game state..!), so anything dealing with circle orders will necessarily be weird.
{
order = DORDER_CIRCLE;
secondarySetState(psDroid, DSO_CIRCLE, DSS_NONE);
}
- else if (secondaryGetState(psDroid, DSO_PATROL) == DSS_PATROL_SET)
+ else if (secondaryGetState(psDroid, DSO_PATROL, ModeQueue) == DSS_PATROL_SET) // ModeQueue here means to check whether we pressed the patrol button, whether or not it synched yet. The reason for this weirdness is that a patrol order makes no sense as a secondary state in the first place (the patrol button _should_ have been only in the UI, not in the game state..!), so anything dealing with patrol orders will necessarily be weird.
{
order = DORDER_PATROL;
secondarySetState(psDroid, DSO_PATROL, DSS_NONE);
@@ -3037,11 +3037,15 @@ bool secondarySupported(DROID *psDroid, SECONDARY_ORDER sec)
/** This function returns the droid order's secondary state of the secondary order.*/
-SECONDARY_STATE secondaryGetState(DROID *psDroid, SECONDARY_ORDER sec)
+SECONDARY_STATE secondaryGetState(DROID *psDroid, SECONDARY_ORDER sec, QUEUE_MODE mode)
{
uint32_t state;
state = psDroid->secondaryOrder;
+ if (mode == ModeQueue)
+ {
+ state = psDroid->secondaryOrderPending; // The UI wants to know the state, so return what the state will be after orders are synchronised.
+ }
switch (sec)
{
@@ -3202,6 +3206,114 @@ bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE Stat
DROID *psTransport, *psCurr, *psNext;
DROID_ORDER order;
+ CurrState = psDroid->secondaryOrder;
+ if (bMultiMessages && mode == ModeQueue)
+ {
+ CurrState = psDroid->secondaryOrderPending;
+ }
+
+ // Figure out what the new secondary state will be (once the order is synchronised.
+ // Why does this have to be so ridiculously complicated?
+ uint32_t secondaryMask = 0;
+ uint32_t secondarySet = 0;
+ switch (sec)
+ {
+ case DSO_ATTACK_RANGE:
+ secondaryMask = DSS_ARANGE_MASK;
+ secondarySet = State;
+ break;
+ case DSO_REPAIR_LEVEL:
+ secondaryMask = DSS_REPLEV_MASK;
+ secondarySet = State;
+ break;
+ case DSO_ATTACK_LEVEL:
+ secondaryMask = DSS_ALEV_MASK;
+ secondarySet = State;
+ break;
+ case DSO_ASSIGN_PRODUCTION:
+ if (psDroid->droidType == DROID_COMMAND)
+ {
+ secondaryMask = DSS_ASSPROD_FACT_MASK;
+ secondarySet = State & DSS_ASSPROD_MASK;
+ }
+ break;
+ case DSO_ASSIGN_CYBORG_PRODUCTION:
+ if (psDroid->droidType == DROID_COMMAND)
+ {
+ secondaryMask = DSS_ASSPROD_CYB_MASK;
+ secondarySet = State & DSS_ASSPROD_MASK;
+ }
+ break;
+ case DSO_ASSIGN_VTOL_PRODUCTION:
+ if (psDroid->droidType == DROID_COMMAND)
+ {
+ secondaryMask = DSS_ASSPROD_VTOL_MASK;
+ secondarySet = State & DSS_ASSPROD_MASK;
+ }
+ break;
+ case DSO_CLEAR_PRODUCTION:
+ if (psDroid->droidType == DROID_COMMAND)
+ {
+ secondaryMask = State & DSS_ASSPROD_MASK;
+ } break;
+ case DSO_RECYCLE:
+ if (State & DSS_RECYCLE_MASK)
+ {
+ secondaryMask = DSS_RTL_MASK | DSS_RECYCLE_MASK | DSS_HALT_MASK;
+ secondarySet = DSS_RECYCLE_SET | DSS_HALT_GUARD;
+ }
+ else
+ {
+ secondaryMask = DSS_RECYCLE_MASK;
+ }
+ break;
+ case DSO_CIRCLE: // This doesn't even make any sense whatsoever as a secondary order...
+ secondaryMask = DSS_CIRCLE_MASK;
+ secondarySet = (State & DSS_CIRCLE_SET)? DSS_CIRCLE_SET : 0;
+ break;
+ case DSO_PATROL: // This doesn't even make any sense whatsoever as a secondary order...
+ secondaryMask = DSS_PATROL_MASK;
+ secondarySet = (State & DSS_PATROL_SET)? DSS_PATROL_SET : 0;
+ break;
+ case DSO_HALTTYPE:
+ switch (State & DSS_HALT_MASK)
+ {
+ case DSS_HALT_PURSUE:
+ case DSS_HALT_GUARD:
+ case DSS_HALT_HOLD:
+ secondaryMask = DSS_HALT_MASK;
+ secondarySet = State;
+ break;
+ }
+ break;
+ case DSO_RETURN_TO_LOC:
+ secondaryMask = DSS_RTL_MASK;
+ switch (State & DSS_RTL_MASK)
+ {
+ case DSS_RTL_REPAIR:
+ case DSS_RTL_BASE:
+ secondarySet = State;
+ break;
+ case DSS_RTL_TRANSPORT:
+ psTransport = FindATransporter(psDroid->player);
+ if (psTransport != NULL && !(bMultiPlayer && !cyborgDroid(psDroid)))
+ {
+ secondarySet = State;
+ }
+ break;
+ }
+ if ((CurrState & DSS_HALT_MASK) == DSS_HALT_HOLD)
+ {
+ secondaryMask |= DSS_HALT_MASK;
+ secondarySet |= DSS_HALT_GUARD;
+ }
+ break;
+ case DSO_FIRE_DESIGNATOR:
+ // Do nothing.
+ break;
+ }
+ uint32_t newSecondaryState = (CurrState & ~secondaryMask) | secondarySet;
+
if (bMultiMessages && mode == ModeQueue)
{
if (sec == DSO_REPAIR_LEVEL)
@@ -3210,6 +3322,8 @@ bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE Stat
}
sendDroidSecondary(psDroid,sec,State);
+ psDroid->secondaryOrderPending = newSecondaryState;
+ ++psDroid->secondaryOrderPendingCount;
return true; // Wait for our order before changing the droid.
}
@@ -3223,10 +3337,9 @@ bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE Stat
psDroid->psGroup->setSecondary(sec, State);
}
- CurrState = psDroid->secondaryOrder;
-
retVal = true;
- switch (sec) {
+ switch (sec)
+ {
case DSO_ATTACK_RANGE:
CurrState = (CurrState & ~DSS_ARANGE_MASK) | State;
break;
@@ -3516,7 +3629,16 @@ bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE Stat
break;
}
+ if (CurrState != newSecondaryState)
+ {
+ debug(LOG_WARNING, "Guessed the new secondary state incorrectly, expected 0x%08X, got 0x%08X, was 0x%08X, sec = %d, state = 0x%08X.", newSecondaryState, CurrState, psDroid->secondaryOrder, sec, State);
+ }
psDroid->secondaryOrder = CurrState;
+ psDroid->secondaryOrderPendingCount = std::max(psDroid->secondaryOrderPendingCount - 1, 0);
+ if (psDroid->secondaryOrderPendingCount == 0)
+ {
+ psDroid->secondaryOrderPending = psDroid->secondaryOrder; // If no orders are pending, make sure UI uses the actual state.
+ }
return retVal;
}
@@ -3542,7 +3664,7 @@ bool secondaryGotPrimaryOrder(DROID *psDroid, DROID_ORDER order)
//reset 2ndary order
oldState = psDroid->secondaryOrder;
psDroid->secondaryOrder &= ~ (DSS_RTL_MASK|DSS_RECYCLE_MASK|DSS_PATROL_MASK);
-
+ psDroid->secondaryOrderPending &= ~(DSS_RTL_MASK|DSS_RECYCLE_MASK|DSS_PATROL_MASK);
if((oldState != psDroid->secondaryOrder) &&
(psDroid->player == selectedPlayer))
View
2 src/order.h
@@ -112,7 +112,7 @@ void orderSelectedStatsTwoLocDir(UDWORD player, DROID_ORDER order, STRUCTURE_STA
extern bool secondarySupported(DROID *psDroid, SECONDARY_ORDER sec);
/** \brief Gets the state of a secondary order, return false if unsupported. */
-extern SECONDARY_STATE secondaryGetState(DROID *psDroid, SECONDARY_ORDER sec);
+SECONDARY_STATE secondaryGetState(DROID *psDroid, SECONDARY_ORDER sec, QUEUE_MODE mode = ModeImmediate);
/** \brief Sets the state of a secondary order, return false if failed. */
extern bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE State, QUEUE_MODE mode = ModeQueue);
View
10 src/projectile.cpp
@@ -1187,6 +1187,11 @@ static void proj_ImpactFunc( PROJECTILE *psObj )
gridStartIterate(psObj->pos.x, psObj->pos.y, psStats->radius);
for (BASE_OBJECT *psCurr = gridIterate(); psCurr != NULL; psCurr = gridIterate())
{
+ if (psCurr->died)
+ {
+ continue; // Do not damage dead objects further.
+ }
+
if (psCurr == psObj->psDest)
{
continue; // Don't hit main target twice.
@@ -1366,6 +1371,11 @@ static void proj_checkBurnDamage(PROJECTILE *psProj)
gridStartIterate(psProj->pos.x, psProj->pos.y, psStats->incenRadius);
for (BASE_OBJECT *psCurr = gridIterate(); psCurr != NULL; psCurr = gridIterate())
{
+ if (psCurr->died)
+ {
+ continue; // Do not damage dead objects further.
+ }
+
if (aiCheckAlliances(psProj->player, psCurr->player))
{
continue; // Don't damage your own droids, nor ally droids - unrealistic, but better.

No commit comments for this range

Something went wrong with that request. Please try again.