diff --git a/lib/framework/debug.c b/lib/framework/debug.c index 49ea73eb1..d9353a08b 100644 --- a/lib/framework/debug.c +++ b/lib/framework/debug.c @@ -74,6 +74,7 @@ static const char *code_part_names[] = { "gateway", "message", "terrain", + "feature", "last" }; diff --git a/lib/framework/debug.h b/lib/framework/debug.h index 18c25c3bb..22c7cd2ba 100644 --- a/lib/framework/debug.h +++ b/lib/framework/debug.h @@ -139,6 +139,7 @@ typedef enum { LOG_GATEWAY, LOG_MSG, LOG_TERRAIN, + LOG_FEATURE, LOG_LAST /**< _must_ be last! */ } code_part; diff --git a/src/feature.c b/src/feature.c index 4600244d6..93ea70e8d 100644 --- a/src/feature.c +++ b/src/feature.c @@ -254,6 +254,7 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,BOOL FromSave) FEATURE* psFeature = createFeature(); if (psFeature == NULL) { + debug(LOG_WARNING, "Feature couldn't be built."); return NULL; } // features are not in the cluster system diff --git a/src/move.c b/src/move.c index 37578d1ed..650cb411d 100644 --- a/src/move.c +++ b/src/move.c @@ -2912,7 +2912,11 @@ static void checkLocalFeatures(DROID *psDroid) { SDWORD i; 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. if(psDroid->player != selectedPlayer) { @@ -2920,7 +2924,7 @@ static void checkLocalFeatures(DROID *psDroid) } droidGetNaybors(psDroid);// update naybor list. - + ASSERT( numNaybors <= MAX_NAYBORS, "numNaybors is %d, out of range of %d!", numNaybors, MAX_NAYBORS); // scan the neighbours for(i=0; i<(SDWORD)numNaybors; i++) { @@ -2928,26 +2932,43 @@ static void checkLocalFeatures(DROID *psDroid) psObj = asDroidNaybors[i].psObj; if ( psObj->type != OBJ_FEATURE || ((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 continue; } - if(bMultiPlayer && (psObj->player == ANYPLAYER)) { 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 - { 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. + } + // 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; } } diff --git a/src/multigifts.c b/src/multigifts.c index 64af989d4..dfd0b2e05 100644 --- a/src/multigifts.c +++ b/src/multigifts.c @@ -311,6 +311,7 @@ void giftPower(uint8_t from, uint8_t to, BOOL send) if (from == ANYPLAYER) { gifval = OILDRUM_POWER; + CONPRINTF(ConsoleString,(ConsoleString,_("Player %u found %u power in an oil drum"), to, gifval)); } else { @@ -321,10 +322,6 @@ void giftPower(uint8_t from, uint8_t to, BOOL send) addPower(to, gifval); - if (from == ANYPLAYER && to == selectedPlayer) - { - CONPRINTF(ConsoleString,(ConsoleString,_("You found %u power in an oil drum"),gifval)); - } if (send) { 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. void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type) @@ -613,6 +627,7 @@ void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type) uint32_t x, y; uint8_t player = ANYPLAYER; + debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]); NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS); NETuint8_t(&quantity); NETenum(&type); @@ -630,7 +645,8 @@ void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type) 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); @@ -671,6 +687,7 @@ void recvMultiPlayerRandomArtifacts() 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++) @@ -684,13 +701,13 @@ void recvMultiPlayerRandomArtifacts() 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; } psTile = mapTile(tx, ty); 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; } @@ -700,6 +717,10 @@ void recvMultiPlayerRandomArtifacts() pF->id = ref; pF->player = player; } + else + { + debug(LOG_ERROR, "Couldn't build feature %u for player %u ?", ref, player); + } } NETend(); } diff --git a/src/multiopt.c b/src/multiopt.c index 18761231d..fb52a68bc 100644 --- a/src/multiopt.c +++ b/src/multiopt.c @@ -849,7 +849,8 @@ static BOOL campInit(void) // add free research gifts.. if(NetPlay.bHost) { - addOilDrum( NetPlay.playercount*2 ); // add some free power. + // NOTE: you can set this safely to 50 for testing. + addOilDrum( NetPlay.playercount*2); // add some free power. } playerResponding(); // say howdy! diff --git a/src/multiplay.c b/src/multiplay.c index bb4021113..990f0bae3 100644 --- a/src/multiplay.c +++ b/src/multiplay.c @@ -123,8 +123,8 @@ BOOL turnOffMultiMsg(BOOL bDoit) { if(bTemp == true) { - // Surely, this should be a Assert? - debug(LOG_ERROR, "multiple calls to turn off"); + // This is spammed multiple times. + debug(LOG_NEVER, "multiple calls to turn off"); } if(bMultiPlayer) { @@ -1479,10 +1479,13 @@ static BOOL recvDestroyTemplate() // send a destruct feature message. BOOL SendDestroyFeature(FEATURE *pF) { - // Only send if it is our responsibility - if (myResponsibility(pF->player)) + // Since ANYPLAYER is supposed to be controlled by host only, that creates a issue when + // 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; - + } + debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName); NETbeginEncode(NET_FEATUREDEST, NET_ALL_PLAYERS); NETuint32_t(&pF->id); return NETend(); @@ -1502,9 +1505,11 @@ BOOL recvDestroyFeature() if (pF == NULL) { + debug(LOG_WARNING, "feature id %d not found? (sync error?)", id); return false; } + debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName); // Remove the feature locally turnOffMultiMsg(true); removeFeature(pF);