Synchronise barrel and artefact placement.

Artefacts are now dropped by factories, again. Even if the structure was destroyed
without using debug mode.
master
Cyp 2012-03-31 17:12:54 +02:00
parent ea243df7c0
commit 29966c5da2
8 changed files with 58 additions and 150 deletions

View File

@ -3589,7 +3589,6 @@ const char *messageTypeToString(unsigned messageType_)
case GAME_TEMPLATEDEST: return "GAME_TEMPLATEDEST";
case GAME_ALLIANCE: return "GAME_ALLIANCE";
case GAME_GIFT: return "GAME_GIFT";
case GAME_ARTIFACTS: return "GAME_ARTIFACTS";
case GAME_LASSAT: return "GAME_LASSAT";
case GAME_GAME_TIME: return "GAME_GAME_TIME";
case GAME_PLAYER_LEFT: return "GAME_PLAYER_LEFT";

View File

@ -99,7 +99,6 @@ enum MESSAGE_TYPES
GAME_TEMPLATEDEST, ///< remove template
GAME_ALLIANCE, ///< alliance data.
GAME_GIFT, ///< a luvly gift between players.
GAME_ARTIFACTS, ///< artifacts randomly placed.
GAME_LASSAT, ///< lassat firing.
GAME_GAME_TIME, ///< Game time. Used for synchronising, so that all messages are executed at the same gameTime on all clients.
GAME_PLAYER_LEFT, ///< Player has left or dropped.

View File

@ -517,41 +517,33 @@ bool recvAlliance(NETQUEUE queue, bool allowAudio)
// add an artifact on destruction if required.
void technologyGiveAway(const STRUCTURE *pS)
{
uint8_t count = 1;
FEATURE_TYPE type = FEAT_GEN_ARTE;
syncDebug("Adding artefact.");
// If a fully built factory (or with modules under construction) which is our responsibility got destroyed
if (pS->pStructureType->type == REF_FACTORY && (pS->status == SS_BUILT || pS->currentBuildPts >= pS->body)
&& myResponsibility(pS->player))
int featureIndex;
for (featureIndex = 0; featureIndex < numFeatureStats && asFeatureStats[featureIndex].subType != FEAT_GEN_ARTE; ++featureIndex) {}
if (featureIndex >= numFeatureStats)
{
uint32_t x = map_coord(pS->pos.x);
uint32_t y = map_coord(pS->pos.y);
uint32_t id = generateNewObjectId();
// Pick a tile to place the artifact
if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
{
ASSERT(false, "technologyGiveAway: Unable to find a free location");
}
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ARTIFACTS);
{
/* Make sure that we don't have to violate the constness of pS.
* Since the nettype functions aren't const correct when sending
*/
uint8_t player = pS->player;
NETuint8_t(&count);
NETenum(&type);
NETuint32_t(&x);
NETuint32_t(&y);
NETuint32_t(&id);
NETuint8_t(&player);
}
NETend();
debug(LOG_WARNING, "No artefact feature!");
return;
}
return;
uint32_t x = map_coord(pS->pos.x), y = map_coord(pS->pos.y);
if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
{
syncDebug("Did not find location for oil drum.");
debug(LOG_FEATURE, "Unable to find a free location.");
return;
}
FEATURE *pF = buildFeature(&asFeatureStats[featureIndex], world_coord(x), world_coord(y), false);
if (pF)
{
pF->player = pS->player;
syncDebugFeature(pF, '+');
}
else
{
debug(LOG_ERROR, "Couldn't build artefact?");
}
}
/** Sends a build order for the given feature type to all players
@ -604,132 +596,52 @@ void recvMultiPlayerFeature(NETQUEUE queue)
}
}
}
// must match _feature_type in featuredef.h
static const char *feature_names[] =
{
"FEAT_UNUSED",
"FEAT_HOVER",
"FEAT_TANK",
"FEAT_GEN_ARTE",
"FEAT_OIL_RESOURCE",
"FEAT_BOULDER",
"FEAT_VEHICLE",
"FEAT_BUILDING",
"FEAT_UNUSED",
"FEAT_LOS_OBJ",
"FEAT_OIL_DRUM",
"FEAT_TREE",
"FEAT_SKYSCRAPER",
};
///////////////////////////////////////////////////////////////////////////////
// splatter artifact gifts randomly about.
void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
{
int i, count;
uint32_t x, y;
uint8_t player = ANYPLAYER;
debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]);
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ARTIFACTS);
NETuint8_t(&quantity);
NETenum(&type);
ASSERT(mapWidth > 20, "map not big enough");
ASSERT(mapHeight > 20, "map not big enough");
for (count = 0; count < quantity; count++)
{
uint32_t id = generateNewObjectId();
for (i = 0; i < 3; i++) // try three times
{
// Between 10 and mapwidth - 10
x = (rand()%(mapWidth - 20)) + 10;
y = (rand()%(mapHeight - 20)) + 10;
if (pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
{
break;
}
else if (i == 2)
{
debug(LOG_FEATURE, "Unable to find a free location after 3 tries; giving up.");
x = INVALID_XY;
}
}
NETuint32_t(&x);
NETuint32_t(&y);
NETuint32_t(&id);
NETuint8_t(&player);
}
NETend();
}
// ///////////////////////////////////////////////////////////////
bool addOilDrum(uint8_t count)
{
addMultiPlayerRandomArtifacts(count, FEAT_OIL_DRUM);
return true;
}
syncDebug("Adding %d oil drums.", count);
// ///////////////////////////////////////////////////////////////
// receive splattered artifacts
void recvMultiPlayerRandomArtifacts(NETQUEUE queue)
{
int count, i;
uint8_t quantity, player;
uint32_t tx,ty;
uint32_t ref;
FEATURE_TYPE type = FEAT_TREE; // Dummy initialisation.
FEATURE *pF;
NETbeginDecode(queue, GAME_ARTIFACTS);
NETuint8_t(&quantity);
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 (count = 0; count < quantity; count++)
int featureIndex;
for (featureIndex = 0; featureIndex < numFeatureStats && asFeatureStats[featureIndex].subType != FEAT_OIL_DRUM; ++featureIndex) {}
if (featureIndex >= numFeatureStats)
{
MAPTILE *psTile;
debug(LOG_WARNING, "No oil drum feature!");
return false; // Return value ignored.
}
NETuint32_t(&tx);
NETuint32_t(&ty);
NETuint32_t(&ref);
NETuint8_t(&player);
if (tx == INVALID_XY)
for (unsigned n = 0; n < count; ++n)
{
uint32_t x, y;
for (int i = 0; i < 3; ++i) // try three times
{
// Between 10 and mapwidth - 10
x = gameRand(mapWidth - 20) + 10;
y = gameRand(mapHeight - 20) + 10;
if (pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
{
break;
}
x = INVALID_XY;
}
if (x == INVALID_XY)
{
syncDebug("Did not find location for oil drum.");
debug(LOG_FEATURE, "Unable to find a free location.");
continue;
}
else if (!tileOnMap(tx, ty))
{
debug(LOG_ERROR, "Bad tile coordinates (%u,%u)", tx, ty);
continue;
}
psTile = mapTile(tx, ty);
if (!psTile || psTile->psObject != NULL)
{
debug(LOG_ERROR, "Already something at (%u,%u)!", tx, ty);
continue;
}
pF = buildFeature((asFeatureStats + i), world_coord(tx), world_coord(ty), false);
FEATURE *pF = buildFeature(&asFeatureStats[featureIndex], world_coord(x), world_coord(y), false);
if (pF)
{
pF->id = ref;
pF->player = player;
pF->player = ANYPLAYER;
syncDebugFeature(pF, '+');
}
else
{
debug(LOG_ERROR, "Couldn't build feature %u for player %u ?", ref, player);
debug(LOG_ERROR, "Couldn't build oil drum?");
}
}
NETend();
return true;
}
// ///////////////////////////////////////////////////////////////

View File

@ -35,8 +35,6 @@ extern bool sendGift (uint8_t type, uint8_t to);
extern bool recvGift (NETQUEUE queue);
extern void technologyGiveAway (const STRUCTURE* pS);
extern void recvMultiPlayerRandomArtifacts (NETQUEUE queue);
extern void addMultiPlayerRandomArtifacts (uint8_t quantity, FEATURE_TYPE type);
extern void recvMultiPlayerFeature (NETQUEUE queue);
extern void sendMultiPlayerFeature(FEATURE_TYPE type, uint32_t x, uint32_t y, uint32_t id);

View File

@ -406,10 +406,12 @@ static bool gameInit(void)
game.skDiff[scavengerPlayer()] = DIFF_SLIDER_STOPS / 2;
}
if (NetPlay.isHost) // add oil drums
unsigned playerCount = 0;
for (int index = 0; index < game.maxPlayers; ++index)
{
addOilDrum(NetPlay.playercount * 2);
playerCount += NetPlay.players[index].ai >= 0 || NetPlay.players[index].allocated;
}
addOilDrum(playerCount * 2); // Calculating playerCount instead of using NetPlay.playercount, since the latter seems to be 0 for non-hosts.
playerResponding(); // say howdy!

View File

@ -718,9 +718,6 @@ bool recvMessage(void)
startMultiplayerGame();
}
break;
case GAME_ARTIFACTS:
recvMultiPlayerRandomArtifacts(queue);
break;
case GAME_ALLIANCE:
recvAlliance(queue, true);
break;

View File

@ -163,7 +163,6 @@ bool recvBuildFinished(NETQUEUE queue)
// Inform others that a structure has been destroyed
bool SendDestroyStructure(STRUCTURE *s)
{
technologyGiveAway(s);
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEBUG_REMOVE_STRUCTURE);
// Struct to destroy

View File

@ -4642,6 +4642,8 @@ bool destroyStruct(STRUCTURE *psDel, unsigned impactTime)
CHECK_STRUCTURE(psDel);
technologyGiveAway(psDel); // Drop an artefact, if applicable.
/* Firstly, are we dealing with a wall section */
const bool bMinor = psDel->pStructureType->type == REF_WALL || psDel->pStructureType->type == REF_WALLCORNER;
const bool bDerrick = psDel->pStructureType->type == REF_RESOURCE_EXTRACTOR;