Feature fixes & enhancements.
*Adds LOG_FEATURE (--debug feature) so we can keep track of features. *Disallow VTOLs from being able to poach features. *Changes feature spawning from instant to a variable time period. *When feature can't be placed, break out of routine instead of sending invalid data. *Actually remove features, and notify others that the feature was removed. (AKA, actually sync between machines.) ASSERT() when numNaybors is invalid. Fix a spamming debug line mistakenly changed in r6677 git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@6737 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
df0ada9a50
commit
fc8bbc5bd9
|
@ -74,6 +74,7 @@ static const char *code_part_names[] = {
|
||||||
"gateway",
|
"gateway",
|
||||||
"message",
|
"message",
|
||||||
"terrain",
|
"terrain",
|
||||||
|
"feature",
|
||||||
"last"
|
"last"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,7 @@ typedef enum {
|
||||||
LOG_GATEWAY,
|
LOG_GATEWAY,
|
||||||
LOG_MSG,
|
LOG_MSG,
|
||||||
LOG_TERRAIN,
|
LOG_TERRAIN,
|
||||||
|
LOG_FEATURE,
|
||||||
LOG_LAST /**< _must_ be last! */
|
LOG_LAST /**< _must_ be last! */
|
||||||
} code_part;
|
} code_part;
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,7 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,BOOL FromSave)
|
||||||
FEATURE* psFeature = createFeature();
|
FEATURE* psFeature = createFeature();
|
||||||
if (psFeature == NULL)
|
if (psFeature == NULL)
|
||||||
{
|
{
|
||||||
|
debug(LOG_WARNING, "Feature couldn't be built.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// features are not in the cluster system
|
// features are not in the cluster system
|
||||||
|
|
33
src/move.c
33
src/move.c
|
@ -2912,7 +2912,11 @@ static void checkLocalFeatures(DROID *psDroid)
|
||||||
{
|
{
|
||||||
SDWORD i;
|
SDWORD i;
|
||||||
BASE_OBJECT *psObj;
|
BASE_OBJECT *psObj;
|
||||||
|
static int oilTimer = 0;
|
||||||
|
static bool GenerateDrum = false;
|
||||||
|
static uint8_t drumCount = 0;
|
||||||
|
|
||||||
|
// NOTE: Why not do this for AI units also?
|
||||||
// only do for players droids.
|
// only do for players droids.
|
||||||
if(psDroid->player != selectedPlayer)
|
if(psDroid->player != selectedPlayer)
|
||||||
{
|
{
|
||||||
|
@ -2920,7 +2924,7 @@ static void checkLocalFeatures(DROID *psDroid)
|
||||||
}
|
}
|
||||||
|
|
||||||
droidGetNaybors(psDroid);// update naybor list.
|
droidGetNaybors(psDroid);// update naybor list.
|
||||||
|
ASSERT( numNaybors <= MAX_NAYBORS, "numNaybors is %d, out of range of %d!", numNaybors, MAX_NAYBORS);
|
||||||
// scan the neighbours
|
// scan the neighbours
|
||||||
for(i=0; i<(SDWORD)numNaybors; i++)
|
for(i=0; i<(SDWORD)numNaybors; i++)
|
||||||
{
|
{
|
||||||
|
@ -2928,26 +2932,43 @@ static void checkLocalFeatures(DROID *psDroid)
|
||||||
psObj = asDroidNaybors[i].psObj;
|
psObj = asDroidNaybors[i].psObj;
|
||||||
if ( psObj->type != OBJ_FEATURE
|
if ( psObj->type != OBJ_FEATURE
|
||||||
|| ((FEATURE *)psObj)->psStats->subType != FEAT_OIL_DRUM
|
|| ((FEATURE *)psObj)->psStats->subType != FEAT_OIL_DRUM
|
||||||
|| asDroidNaybors[i].distSqr >= DROIDDIST )
|
|| asDroidNaybors[i].distSqr >= DROIDDIST
|
||||||
|
|| isVtolDroid(psDroid)) // VTOLs can't pick up features!
|
||||||
{
|
{
|
||||||
// object too far away to worry about
|
// object too far away to worry about
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(bMultiPlayer && (psObj->player == ANYPLAYER))
|
if(bMultiPlayer && (psObj->player == ANYPLAYER))
|
||||||
{
|
{
|
||||||
giftPower(ANYPLAYER,selectedPlayer,true); // give power and tell everyone.
|
giftPower(ANYPLAYER,selectedPlayer,true); // give power and tell everyone.
|
||||||
addOilDrum(1);
|
// when player finds oil, we init the timer, and flag that we need a drum
|
||||||
|
if (!oilTimer)
|
||||||
|
{
|
||||||
|
oilTimer = gameTime2;
|
||||||
|
GenerateDrum = true;
|
||||||
|
}
|
||||||
|
// if player finds more than one drum (before timer expires), then we tack on ~50 sec to timer.
|
||||||
|
if(drumCount++)
|
||||||
|
{
|
||||||
|
oilTimer += GAME_TICKS_PER_SEC * 50;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
||||||
{
|
{
|
||||||
addPower(selectedPlayer,OILDRUM_POWER);
|
addPower(selectedPlayer,OILDRUM_POWER);
|
||||||
CONPRINTF(ConsoleString,(ConsoleString,_("You found %u power in an oil drum"),OILDRUM_POWER));
|
CONPRINTF(ConsoleString,(ConsoleString,_("You found %u power in an oil drum."),OILDRUM_POWER));
|
||||||
}
|
}
|
||||||
removeFeature((FEATURE*)psObj); // remove artifact+ send multiplay info.
|
removeFeature((FEATURE*)psObj); // remove artifact+ send multiplay info.
|
||||||
|
}
|
||||||
|
|
||||||
|
// once they found a oil drum, we then wait ~600 secs before we pop up new one(s).
|
||||||
|
if( ((oilTimer + GAME_TICKS_PER_SEC * 600) < gameTime2 ) && GenerateDrum )
|
||||||
|
{
|
||||||
|
addOilDrum(drumCount);
|
||||||
|
oilTimer = 0;
|
||||||
|
drumCount = 0;
|
||||||
|
GenerateDrum = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -311,6 +311,7 @@ void giftPower(uint8_t from, uint8_t to, BOOL send)
|
||||||
if (from == ANYPLAYER)
|
if (from == ANYPLAYER)
|
||||||
{
|
{
|
||||||
gifval = OILDRUM_POWER;
|
gifval = OILDRUM_POWER;
|
||||||
|
CONPRINTF(ConsoleString,(ConsoleString,_("Player %u found %u power in an oil drum"), to, gifval));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -321,10 +322,6 @@ void giftPower(uint8_t from, uint8_t to, BOOL send)
|
||||||
|
|
||||||
addPower(to, gifval);
|
addPower(to, gifval);
|
||||||
|
|
||||||
if (from == ANYPLAYER && to == selectedPlayer)
|
|
||||||
{
|
|
||||||
CONPRINTF(ConsoleString,(ConsoleString,_("You found %u power in an oil drum"),gifval));
|
|
||||||
}
|
|
||||||
if (send)
|
if (send)
|
||||||
{
|
{
|
||||||
uint8_t giftType = POWER_GIFT;
|
uint8_t giftType = POWER_GIFT;
|
||||||
|
@ -604,6 +601,23 @@ void recvMultiPlayerFeature()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// must match _feature_type in featuredef.h
|
||||||
|
static const char *feature_names[] =
|
||||||
|
{
|
||||||
|
"FEAT_BUILD_WRECK",
|
||||||
|
"FEAT_HOVER",
|
||||||
|
"FEAT_TANK",
|
||||||
|
"FEAT_GEN_ARTE",
|
||||||
|
"FEAT_OIL_RESOURCE",
|
||||||
|
"FEAT_BOULDER",
|
||||||
|
"FEAT_VEHICLE",
|
||||||
|
"FEAT_BUILDING",
|
||||||
|
"FEAT_DROID",
|
||||||
|
"FEAT_LOS_OBJ",
|
||||||
|
"FEAT_OIL_DRUM",
|
||||||
|
"FEAT_TREE",
|
||||||
|
"FEAT_SKYSCRAPER",
|
||||||
|
};
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// splatter artifact gifts randomly about.
|
// splatter artifact gifts randomly about.
|
||||||
void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
|
void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
|
||||||
|
@ -613,6 +627,7 @@ void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
|
||||||
uint32_t x, y;
|
uint32_t x, y;
|
||||||
uint8_t player = ANYPLAYER;
|
uint8_t player = ANYPLAYER;
|
||||||
|
|
||||||
|
debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]);
|
||||||
NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
|
NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
|
||||||
NETuint8_t(&quantity);
|
NETuint8_t(&quantity);
|
||||||
NETenum(&type);
|
NETenum(&type);
|
||||||
|
@ -630,7 +645,8 @@ void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
|
||||||
|
|
||||||
if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
|
if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
|
||||||
{
|
{
|
||||||
ASSERT(false, "addMultiPlayerRandomArtifacts: Unable to find a free location");
|
ASSERT(false, "Unable to find a free location");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pF = buildFeature(asFeatureStats + i, world_coord(x), world_coord(y), false);
|
pF = buildFeature(asFeatureStats + i, world_coord(x), world_coord(y), false);
|
||||||
|
@ -671,6 +687,7 @@ void recvMultiPlayerRandomArtifacts()
|
||||||
NETuint8_t(&quantity);
|
NETuint8_t(&quantity);
|
||||||
NETenum(&type);
|
NETenum(&type);
|
||||||
|
|
||||||
|
debug(LOG_FEATURE, "receiving %u artifact(s) type: (%s)", quantity, feature_names[type]);
|
||||||
for (i = 0; i < numFeatureStats && asFeatureStats[i].subType != type; i++);
|
for (i = 0; i < numFeatureStats && asFeatureStats[i].subType != type; i++);
|
||||||
|
|
||||||
for (count = 0; count < quantity; count++)
|
for (count = 0; count < quantity; count++)
|
||||||
|
@ -684,13 +701,13 @@ void recvMultiPlayerRandomArtifacts()
|
||||||
|
|
||||||
if (!tileOnMap(tx, ty))
|
if (!tileOnMap(tx, ty))
|
||||||
{
|
{
|
||||||
debug(LOG_ERROR, "recvMultiPlayerRandomArtifacts: Bad tile coordinates (%u,%u)", tx, ty);
|
debug(LOG_ERROR, "Bad tile coordinates (%u,%u)", tx, ty);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
psTile = mapTile(tx, ty);
|
psTile = mapTile(tx, ty);
|
||||||
if (!psTile || psTile->psObject != NULL)
|
if (!psTile || psTile->psObject != NULL)
|
||||||
{
|
{
|
||||||
debug(LOG_ERROR, "recvMultiPlayerRandomArtifacts: Already something at (%u,%u)!", tx, ty);
|
debug(LOG_ERROR, "Already something at (%u,%u)!", tx, ty);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,6 +717,10 @@ void recvMultiPlayerRandomArtifacts()
|
||||||
pF->id = ref;
|
pF->id = ref;
|
||||||
pF->player = player;
|
pF->player = player;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug(LOG_ERROR, "Couldn't build feature %u for player %u ?", ref, player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NETend();
|
NETend();
|
||||||
}
|
}
|
||||||
|
|
|
@ -849,6 +849,7 @@ static BOOL campInit(void)
|
||||||
// add free research gifts..
|
// add free research gifts..
|
||||||
if(NetPlay.bHost)
|
if(NetPlay.bHost)
|
||||||
{
|
{
|
||||||
|
// NOTE: you can set this safely to 50 for testing.
|
||||||
addOilDrum( NetPlay.playercount*2); // add some free power.
|
addOilDrum( NetPlay.playercount*2); // add some free power.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,8 @@ BOOL turnOffMultiMsg(BOOL bDoit)
|
||||||
{
|
{
|
||||||
if(bTemp == true)
|
if(bTemp == true)
|
||||||
{
|
{
|
||||||
// Surely, this should be a Assert?
|
// This is spammed multiple times.
|
||||||
debug(LOG_ERROR, "multiple calls to turn off");
|
debug(LOG_NEVER, "multiple calls to turn off");
|
||||||
}
|
}
|
||||||
if(bMultiPlayer)
|
if(bMultiPlayer)
|
||||||
{
|
{
|
||||||
|
@ -1479,10 +1479,13 @@ static BOOL recvDestroyTemplate()
|
||||||
// send a destruct feature message.
|
// send a destruct feature message.
|
||||||
BOOL SendDestroyFeature(FEATURE *pF)
|
BOOL SendDestroyFeature(FEATURE *pF)
|
||||||
{
|
{
|
||||||
// Only send if it is our responsibility
|
// Since ANYPLAYER is supposed to be controlled by host only, that creates a issue when
|
||||||
if (myResponsibility(pF->player))
|
// a MP player gets a feature, and it is 'ANYPLAYER' it would never send the destroy msg.
|
||||||
|
if (!myResponsibility(pF->player) || !(pF->player == ANYPLAYER))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName);
|
||||||
NETbeginEncode(NET_FEATUREDEST, NET_ALL_PLAYERS);
|
NETbeginEncode(NET_FEATUREDEST, NET_ALL_PLAYERS);
|
||||||
NETuint32_t(&pF->id);
|
NETuint32_t(&pF->id);
|
||||||
return NETend();
|
return NETend();
|
||||||
|
@ -1502,9 +1505,11 @@ BOOL recvDestroyFeature()
|
||||||
|
|
||||||
if (pF == NULL)
|
if (pF == NULL)
|
||||||
{
|
{
|
||||||
|
debug(LOG_WARNING, "feature id %d not found? (sync error?)", id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName);
|
||||||
// Remove the feature locally
|
// Remove the feature locally
|
||||||
turnOffMultiMsg(true);
|
turnOffMultiMsg(true);
|
||||||
removeFeature(pF);
|
removeFeature(pF);
|
||||||
|
|
Loading…
Reference in New Issue