Exemplo n.º 1
0
/** Receive droid and transporter loading information
 *
 *  \sa sendDroidEmbark(),sendDroidDisEmbark(),recvDroidDisEmbark()
 */
BOOL recvDroidEmbark(NETQUEUE queue)
{
	DROID* psDroid;
	DROID* psTransporterDroid;
	BOOL bDroidRemoved;

	NETbeginDecode(queue, GAME_DROIDEMBARK);
	{
		uint8_t player;
		uint32_t droidID;
		uint32_t transporterID;

		NETuint8_t(&player);
		NETuint32_t(&droidID);
		NETuint32_t(&transporterID);

		// we have to find the droid on our (local) list first.
		if (!IdToDroid(droidID, player, &psDroid))
		{
			NETend();
			// Possible it already died? (sync error?)
			debug(LOG_WARNING, "player's %d droid %d wasn't found?", player,droidID);
			return false;
		}
		if (!IdToDroid(transporterID, player, &psTransporterDroid))
		{
			NETend();
			// Possible it already died? (sync error?)
			debug(LOG_WARNING, "player's %d transport droid %d wasn't found?", player,transporterID);
			return false;
		}

		if (psDroid == NULL)
		{
			// how can this happen?
			return true;
		}

		// Take it out of the world without destroying it (just removes it from the droid list)
		bDroidRemoved = droidRemove(psDroid, apsDroidLists);

		// Init the order for when disembark
		psDroid->order = DORDER_NONE;
		setDroidTarget(psDroid, NULL);
		psDroid->psTarStats = NULL;

		if (bDroidRemoved)
		{
			// and now we need to add it to their transporter group!
			grpJoin(psTransporterDroid->psGroup, psDroid);
		}
		else
		{
			// possible sync error?
			debug(LOG_WARNING, "Eh? Where did unit %d go? Couldn't load droid onto transporter.", droidID);
		}
	}
	NETend();
	return true;
}
Exemplo n.º 2
0
// recv
BOOL recvDroidSecondary(NETQUEUE queue)
{
	DROID*          psDroid;
	SECONDARY_ORDER sec = DSO_ATTACK_RANGE;
	SECONDARY_STATE state = DSS_NONE;

	NETbeginDecode(queue, GAME_SECONDARY);
	{
		uint8_t player;
		uint32_t droid;

		NETuint8_t(&player);
		NETuint32_t(&droid);
		NETenum(&sec);
		NETenum(&state);

		// If we can not find the droid should we not ask for it?
		if (!IdToDroid(droid, player, &psDroid))
		{
			NETend();
			return false;
		}
	}
	NETend();

	// Set the droids secondary order
	turnOffMultiMsg(true);
	secondarySetState(psDroid, sec, state);
	turnOffMultiMsg(false);

	return true;
}
Exemplo n.º 3
0
BOOL recvDemolishFinished(NETQUEUE queue)
{
	STRUCTURE	*psStruct;
	DROID		*psDroid;
	uint32_t	structID, droidID;

	NETbeginDecode(queue, GAME_DEMOLISH);
		NETuint32_t(&structID);
		NETuint32_t(&droidID);
	NETend();

	psStruct = IdToStruct(structID, ANYPLAYER);
	if (!IdToDroid(droidID, ANYPLAYER, &psDroid))
	{
		debug(LOG_ERROR, "recvDemolishFinished: Packet with bad droid ID received. Discarding!");
		return false;
	}

	if (psStruct)
	{
		// Demolish it
		// Should never get here, if in synch.
		removeStruct(psStruct, true);
		if (psDroid && psDroid->psTarStats)
		{
			// Update droid if reqd
			psDroid->psTarStats = NULL;
		}
	}

	return true;
}
Exemplo n.º 4
0
// ////////////////////////////////////////////////////////////////////////////
// Accept a droid which was destroyed on another machine
BOOL recvDestroyDroid(NETQUEUE queue)
{
	DROID* psDroid;

	NETbeginDecode(queue, GAME_DROIDDEST);
	{
		uint32_t id;

		// Retrieve the droid
		NETuint32_t(&id);
		if (!IdToDroid(id, ANYPLAYER, &psDroid))
		{
			debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?",
					id, queue.index );
			return false;
		}
	}
	NETend();

	// If the droid has not died on our machine yet, destroy it
	if(!psDroid->died)
	{
		turnOffMultiMsg(true);
		debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index);
		destroyDroid(psDroid);
		turnOffMultiMsg(false);
	}
	else
	{
		debug(LOG_DEATH, "droid %d is confirmed dead by player %d.", psDroid->id, queue.index);
	}

	return true;
}
Exemplo n.º 5
0
/////////////////////////////////////////////////////////////////////////////////
//  Returns a pointer to base object, given an id and optionally a player.
BASE_OBJECT *IdToPointer(UDWORD id,UDWORD player)
{
	DROID		*pD;
	STRUCTURE	*pS;
	FEATURE		*pF;
	// droids.

	pD = IdToDroid(id, player);
	if (pD)
	{
		return (BASE_OBJECT*)pD;
	}

	// structures
	pS = IdToStruct(id,player);
	if(pS)
	{
		return (BASE_OBJECT*)pS;
	}

	// features
	pF = IdToFeature(id,player);
	if(pF)
	{
		return (BASE_OBJECT*)pF;
	}

	return NULL;
}
Exemplo n.º 6
0
/** Receive info about a droid that is being unloaded from a transporter
 */
bool recvDroidDisEmbark(NETQUEUE queue)
{
	DROID *psFoundDroid = NULL, *psTransporterDroid = NULL;
	DROID *psCheckDroid = NULL;

	NETbeginDecode(queue, GAME_DROIDDISEMBARK);
	{
		uint32_t player;
		uint32_t droidID;
		uint32_t transporterID;

		NETuint32_t(&player);
		NETuint32_t(&droidID);
		NETuint32_t(&transporterID);

		NETend();

		// find the transporter first
		psTransporterDroid = IdToDroid(transporterID, player);
		if (!psTransporterDroid)
		{
			// Possible it already died? (sync error?)
			debug(LOG_WARNING, "player's %d transport droid %d wasn't found?", player, transporterID);
			return false;
		}
		if (!canGiveOrdersFor(queue.index, psTransporterDroid->player))
		{
			return false;
		}
		// we need to find the droid *in* the transporter
		psCheckDroid = psTransporterDroid ->psGroup->psList;
		while (psCheckDroid)
		{
			// is this the one we want?
			if (psCheckDroid->id == droidID)
			{
				psFoundDroid = psCheckDroid;
				break;
			}
			// not found, so check next one in *group*
			psCheckDroid = psCheckDroid->psGrpNext;
		}
		// don't continue if we couldn't find it.
		if (!psFoundDroid)
		{
			// I don't think this could ever be possible...but
			debug(LOG_ERROR, "Couldn't find droid %d to disembark from player %d's transporter?", droidID, player);
			return false;
		}

		transporterRemoveDroid(psTransporterDroid, psFoundDroid, ModeImmediate);
	}
	return true;
}
Exemplo n.º 7
0
static QScriptValue js_groupAddDroid(QScriptContext *context, QScriptEngine *engine)
{
	int groupId = context->argument(0).toInt32();
	DROID_GROUP *psGroup = grpFind(groupId);
	QScriptValue droidVal = context->argument(1);
	int droidId = droidVal.property("id").toInt32();
	int droidPlayer = droidVal.property("player").toInt32();
	DROID *psDroid = IdToDroid(droidId, droidPlayer);

	SCRIPT_ASSERT(context, psGroup, "Invalid group index %d", groupId);
	SCRIPT_ASSERT(context, psDroid, "Invalid droid index %d", droidId);
	psGroup->add(psDroid);
	return QScriptValue();
}
Exemplo n.º 8
0
static QScriptValue js_orderDroidLoc(QScriptContext *context, QScriptEngine *)
{
	QScriptValue droidVal = context->argument(0);
	int id = droidVal.property("id").toInt32();
	int player = droidVal.property("player").toInt32();
	QScriptValue orderVal = context->argument(1);
	int x = context->argument(2).toInt32();
	int y = context->argument(3).toInt32();
	DROID_ORDER order = (DROID_ORDER)orderVal.toInt32();
	DROID *psDroid = IdToDroid(id, player);
	SCRIPT_ASSERT(context, psDroid, "Droid id %d not found belonging to player %d", id, player);
	SCRIPT_ASSERT(context, worldOnMap(x, y), "Outside map bounds (%d, %d)", x, y);
	orderDroidLoc(psDroid, order, x, y, ModeQueue);
	return QScriptValue();
}
Exemplo n.º 9
0
// ////////////////////////////////////////////////////////////////////////////
// process droid order
static BASE_OBJECT *processDroidTarget(OBJECT_TYPE desttype, uint32_t destid)
{
	// Target is a location
	if (destid == 0 && desttype == 0)
	{
		return NULL;
	}
	// Target is an object
	else
	{
		BASE_OBJECT *psObj = NULL;
		DROID		*pD;

		switch (desttype)
		{
			case OBJ_DROID:
				if (IdToDroid(destid, ANYPLAYER, &pD))
				{
					psObj = (BASE_OBJECT*)pD;
				}
				break;
			case OBJ_STRUCTURE:
				psObj = (BASE_OBJECT*)IdToStruct(destid,ANYPLAYER);
				break;
			case OBJ_FEATURE:
				psObj = (BASE_OBJECT*)IdToFeature(destid,ANYPLAYER);
				break;

			// We should not get this!
			case OBJ_PROJECTILE:
				debug(LOG_ERROR, "ProcessDroidOrder: order specified destination as a bullet. what am i to do??");
				break;
			default:
				debug(LOG_ERROR, "ProcessDroidOrder: unknown object type");
				break;
		}

		// If we did not find anything, return
		if (!psObj)													// failed to find it;
		{
			syncDebug("Target missing");
			return TargetMissing;  // Can't return NULL, since then the order would still be attempted.
		}

		return psObj;
	}
}
Exemplo n.º 10
0
// recvGiftDroid()
// We received a droid gift from another player.
// NOTICE: the packet is already set-up for decoding via recvGift()
//
// \param from  :player that sent us the droid
// \param to    :player that should be getting the droid
static void recvGiftDroids(uint8_t from, uint8_t to, uint32_t droidID)
{
	DROID		*psDroid;

	if (IdToDroid(droidID, from, &psDroid))
	{
		giftSingleDroid(psDroid, to);
		if (to == selectedPlayer)
		{
			CONPRINTF(ConsoleString, (ConsoleString, _("%s Gives you a %s"), getPlayerName(from), psDroid->aName));
		}
	}
	else
	{
		debug(LOG_ERROR, "Bad droid id %u, from %u to %u", droidID, from, to);
	}
}
Exemplo n.º 11
0
// ////////////////////////////////////////////////////////////////////////////
// Accept a droid which was destroyed on another machine
bool recvDestroyDroid(NETQUEUE queue)
{
	DROID *psDroid;

	NETbeginDecode(queue, GAME_DEBUG_REMOVE_DROID);
	{
		uint32_t id;

		// Retrieve the droid
		NETuint32_t(&id);
		psDroid = IdToDroid(id, ANYPLAYER);
		if (!psDroid)
		{
			debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?",
			      id, queue.index);
			return false;
		}
	}
	NETend();

	if (!getDebugMappingStatus() && bMultiPlayer)
	{
		debug(LOG_WARNING, "Failed to remove droid for player %u.", NetPlay.players[queue.index].position);
		return false;
	}

	// If the droid has not died on our machine yet, destroy it
	if (!psDroid->died)
	{
		turnOffMultiMsg(true);
		debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index);
		destroyDroid(psDroid, gameTime - deltaGameTime + 1);  // deltaGameTime is actually 0 here, since we're between updates. However, the value of gameTime - deltaGameTime + 1 will not change when we start the next tick.
		turnOffMultiMsg(false);
	}
	else
	{
		debug(LOG_DEATH, "droid %d is confirmed dead by player %d.", psDroid->id, queue.index);
	}

	return true;
}
Exemplo n.º 12
0
// ////////////////////////////////////////////////////////////////////////////
// Accept a droid which was destroyed on another machine
bool recvDestroyDroid(NETQUEUE queue)
{
	DROID* psDroid;

	NETbeginDecode(queue, GAME_DEBUG_REMOVE_DROID);
	{
		uint32_t id;

		// Retrieve the droid
		NETuint32_t(&id);
		psDroid = IdToDroid(id, ANYPLAYER);
		if (!psDroid)
		{
			debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?",
					id, queue.index );
			return false;
		}
	}
	NETend();

	if (!getDebugMappingStatus())
	{
		debug(LOG_WARNING, "Failed to remove droid for player %u.", NetPlay.players[queue.index].position);
		return false;
	}

	// If the droid has not died on our machine yet, destroy it
	if(!psDroid->died)
	{
		turnOffMultiMsg(true);
		debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index);
		destroyDroid(psDroid, gameTime);
		turnOffMultiMsg(false);
	}
	else
	{
		debug(LOG_DEATH, "droid %d is confirmed dead by player %d.", psDroid->id, queue.index);
	}

	return true;
}
Exemplo n.º 13
0
BOOL recvDemolishFinished(NETMSG *m)
{
	STRUCTURE	*psStruct;
	UDWORD		s,d;
	DROID		*psDroid;

	NetGet(m,0,s);					
	NetGet(m,4,d);							

	psStruct = IdToStruct(s,ANYPLAYER);
	IdToDroid(d,ANYPLAYER,&psDroid);

	if(psStruct)
	{
		removeStruct( psStruct, TRUE );				// demolish it.
		if(psDroid && psDroid->psTarStats)
		{
			psDroid->psTarStats = NULL;		// update droid if reqd.
		}
	}
	return TRUE;
}
Exemplo n.º 14
0
static QScriptValue js_label(QScriptContext *context, QScriptEngine *engine)
{
	QString label = context->argument(0).toString();
	QScriptValue ret = engine->newObject();
	if (labels.contains(label))
	{
		labeltype p = labels.value(label);
		if (p.type == AREA || p.type == POSITION)
		{
			ret.setProperty("x", map_coord(p.p1.x), QScriptValue::ReadOnly);
			ret.setProperty("y", map_coord(p.p1.y), QScriptValue::ReadOnly);
		}
		if (p.type == AREA)
		{
			ret.setProperty("x2", map_coord(p.p2.x), QScriptValue::ReadOnly);
			ret.setProperty("xy", map_coord(p.p2.y), QScriptValue::ReadOnly);
		}
		else if (p.type == OBJ_DROID)
		{
			DROID *psDroid = IdToDroid(p.id, p.player);
			if (psDroid) ret = convDroid(psDroid, engine);
		}
		else if (p.type == OBJ_STRUCTURE)
		{
			STRUCTURE *psStruct = IdToStruct(p.id, p.player);
			if (psStruct) ret = convStructure(psStruct, engine);
		}
		else if (p.type == OBJ_FEATURE)
		{
			FEATURE *psFeature = IdToFeature(p.id, p.player);
			if (psFeature) ret = convFeature(psFeature, engine);
		}
	}
	else debug(LOG_ERROR, "label %s not found!", label.toUtf8().constData());
	return ret;
}
Exemplo n.º 15
0
// ////////////////////////////////////////////////////////////////////////////
// receive droid information form other players.
BOOL recvDroidInfo(NETQUEUE queue)
{
	NETbeginDecode(queue, GAME_DROIDINFO);
	{
		QueuedDroidInfo info;
		memset(&info, 0x00, sizeof(info));
		NETQueuedDroidInfo(&info);

		STRUCTURE_STATS *psStats = NULL;
		if (info.order == DORDER_BUILD || info.order == DORDER_LINEBUILD)
		{
			// Find structure target
			for (unsigned typeIndex = 0; typeIndex < numStructureStats; typeIndex++)
			{
				if (asStructureStats[typeIndex].ref == info.structRef)
				{
					psStats = asStructureStats + typeIndex;
					break;
				}
			}
		}

		if (info.subType)
		{
			syncDebug("Order=%s,%d(%d)", getDroidOrderName(info.order), info.destId, info.destType);
		}
		else
		{
			syncDebug("Order=%s,(%d,%d)", getDroidOrderName(info.order), info.x, info.y);
		}

		DROID_ORDER_DATA sOrder;
		memset(&sOrder, 0x00, sizeof(sOrder));
		sOrder.order = info.order;
		sOrder.x = info.x;
		sOrder.y = info.y;
		sOrder.x2 = info.x2;
		sOrder.y2 = info.y2;
		sOrder.direction = info.direction;
		sOrder.psObj = processDroidTarget(info.destType, info.destId);
		sOrder.psStats = (BASE_STATS *)psStats;

		uint32_t num = 0;
		NETuint32_t(&num);

		for (unsigned n = 0; n < num; ++n)
		{
			// Get the next droid ID which is being given this order.
			uint32_t deltaDroidId = 0;
			NETuint32_t(&deltaDroidId);
			info.droidId += deltaDroidId;

			DROID *psDroid = NULL;
			if (!IdToDroid(info.droidId, ANYPLAYER, &psDroid))
			{
				debug(LOG_NEVER, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
				      queue.index, info.droidId, isHumanPlayer(info.player) ? "Human" : "AI", info.player);
				syncDebug("Droid %d missing", info.droidId);
				continue;  // Can't find the droid, so skip this droid.
			}

			CHECK_DROID(psDroid);

			syncDebugDroid(psDroid, '<');

			psDroid->waitingForOwnReceiveDroidInfoMessage = false;

			/*
			* If the current order not is a command order and we are not a
			* commander yet are in the commander group remove us from it.
			*/
			if (hasCommander(psDroid))
			{
				grpLeave(psDroid->psGroup, psDroid);
			}

			if (sOrder.psObj != TargetMissing)  // Only do order if the target didn't die.
			{
				orderDroidBase(psDroid, &sOrder);
			}

			syncDebugDroid(psDroid, '>');

			CHECK_DROID(psDroid);
		}
	}
	NETend();

	return true;
}
Exemplo n.º 16
0
/** Receive info about a droid that is being unloaded from a transporter
 *
 *  \sa sendDroidEmbark(),recvDroidEmbark(),sendDroidDisEmbark()
 */
BOOL recvDroidDisEmbark(NETQUEUE queue)
{
	DROID *psFoundDroid = NULL, *psTransporterDroid = NULL;
	DROID *psCheckDroid = NULL;

	NETbeginDecode(queue, GAME_DROIDDISEMBARK);
	{
		uint8_t player;
		uint32_t droidID;
		uint32_t transporterID;
		Position pos;

		NETuint8_t(&player);
		NETuint32_t(&droidID);
		NETuint32_t(&transporterID);
		NETPosition(&pos);

		NETend();

		// find the transporter first
		if (!IdToDroid(transporterID, player, &psTransporterDroid))
		{
			// Possible it already died? (sync error?)
			debug(LOG_WARNING, "player's %d transport droid %d wasn't found?", player, transporterID);
			return false;
		}
		// we need to find the droid *in* the transporter
		psCheckDroid = psTransporterDroid ->psGroup->psList;
		while (psCheckDroid)
		{
			// is this the one we want?
			if( psCheckDroid->id == droidID)
			{
				psFoundDroid = psCheckDroid;
				break;
			}
			// not found, so check next one in *group*
			psCheckDroid = psCheckDroid->psGrpNext;
		}
		// don't continue if we couldn't find it.
		if (!psFoundDroid)
		{
			// I don't think this could ever be possible...but
			debug(LOG_ERROR, "Couldn't find droid %d to disembark from player %d's transporter?", droidID, player);
			return false;
		}

		// remove it from the transporter
		grpLeave(psFoundDroid->psGroup, psFoundDroid);

		// and add it back to the bloody droid list
		addDroid(psFoundDroid, apsDroidLists);

		// Add it back into the world at the x/y
		droidSetPrecisePosition(psFoundDroid, pos);

		if (!droidOnMap(psFoundDroid))
		{
			debug(LOG_ERROR, "droid %d disembarked was NOT on map?", psFoundDroid->id);
			return false;
		}

		updateDroidOrientation(psFoundDroid);

		// Initialise the movement data
		initDroidMovement(psFoundDroid);
	}
	return true;
}
Exemplo n.º 17
0
// ////////////////////////////////////////////////////////////////////////////
// put down a base plate and start droid building it!
BOOL recvBuildStarted()
{
    STRUCTURE_STATS *psStats;
    DROID			*psDroid;
    UDWORD			actionX,actionY;
    unsigned int typeIndex;
    uint8_t			player;
    uint16_t		x, y, z;
    int32_t			order;
    uint32_t		structRef, structId, targetId,droidID;

    NETbeginDecode(NET_BUILD);
    NETuint8_t(&player);
    NETuint32_t(&structRef);
    NETuint16_t(&x);
    NETuint16_t(&y);
    NETuint32_t(&droidID);
    NETuint32_t(&structId);
    NETint32_t(&order);
    NETuint32_t(&targetId);
    NETuint16_t(&z);
    NETend();
    // Find structure target
    for (typeIndex = 0;
            typeIndex < numStructureStats && asStructureStats[typeIndex].ref != structRef;
            typeIndex++);

    psStats = &asStructureStats[typeIndex];

    if (IdToDroid(droidID, player, &psDroid))
    {
        // Tell the droid to go to where it needs to in order to build the struct
        if (getDroidDestination((BASE_STATS *) psStats, x, y, &actionX, &actionY))
        {
            psDroid->order = order;

            if (psDroid->order == DORDER_LINEBUILD)
            {
                psDroid->order = DORDER_BUILD;
            }

            psDroid->orderX = x;
            psDroid->orderY = y;
            psDroid->psTarStats = (BASE_STATS *) psStats;

            if (targetId)
            {
                setDroidTarget(psDroid, IdToPointer(targetId, ANYPLAYER));
            }
            else
            {
                setDroidTarget(psDroid, NULL);
            }

            if (IsStatExpansionModule(psStats))
            {
                setUpBuildModule(psDroid);
            }
            else
            {
                droidStartBuild(psDroid);
                psDroid->action = DACTION_BUILD;
            }
        }

        // Sync IDs
        if (psDroid->psTarget)
        {
            ((STRUCTURE *) psDroid->psTarget)->id = structId;
        }
    }

    return true;
}
Exemplo n.º 18
0
// ////////////////////////////////////////////////////////////////////////////
// receive a check and update the local world state accordingly
BOOL recvDroidCheck(NETQUEUE queue)
{
	uint8_t		count;
	int		i;
	uint32_t        synchTime;

	NETbeginDecode(queue, GAME_CHECK_DROID);

		// Get the number of droids to expect
		NETuint8_t(&count);
		NETuint32_t(&synchTime);  // Get game time.

		for (i = 0; i < count; i++)
		{
			DROID *         pD;
			PACKAGED_CHECK  pc, pc2;
			Position        precPos;

			NETPACKAGED_CHECK(&pc);

			// Find the droid in question
			if (!IdToDroid(pc.droidID, pc.player, &pD))
			{
				NETlogEntry("Recvd Unknown droid info. val=player", SYNC_FLAG, pc.player);
				debug(LOG_SYNC, "Received checking info for an unknown (as yet) droid. player:%d ref:%d", pc.player, pc.droidID);
				continue;
			}

			syncDebugDroid(pD, '<');

			if (pD->gameCheckDroid == NULL)
			{
				debug(LOG_SYNC, "We got a droid %u synch, but we couldn't find the droid!", pc.droidID);
				continue;  // Can't synch, since we didn't save data to be able to calculate a delta.
			}

			pc2 = *(PACKAGED_CHECK *)pD->gameCheckDroid;  // pc2 should be declared here, as const.

			if (pc2.gameTime != synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS)
			{
				debug(LOG_SYNC, "We got a droid %u synch, but we didn't choose the same droid to synch.", pc.droidID);
				((PACKAGED_CHECK *)pD->gameCheckDroid)->gameTime = synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS;  // Get droid synch time back in synch.
				continue;  // Can't synch, since we didn't save data to be able to calculate a delta.
			}

#define MERGECOPY(x, y, z)  if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, pc.y);             x = pc.y; }
#define MERGEDELTA(x, y, z) if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, x + pc.y - pc2.y); x += pc.y - pc2.y; }
			// player not synched here...
			precPos = droidGetPrecisePosition(pD);
			MERGEDELTA(precPos.x, pos.x, "d");
			MERGEDELTA(precPos.y, pos.y, "d");
			MERGEDELTA(precPos.z, pos.z, "d");
			droidSetPrecisePosition(pD, precPos);
			MERGEDELTA(pD->rot.direction, rot.direction, "d");
			MERGEDELTA(pD->rot.pitch, rot.pitch, "d");
			MERGEDELTA(pD->rot.roll, rot.roll, "d");
			MERGEDELTA(pD->body, body, "u");
			if (pD->body > pD->originalBody)
			{
				pD->body = pD->originalBody;
				debug(LOG_SYNC, "Droid %u body was too high after synch, reducing to %u.", pc.droidID, pD->body);
			}
			MERGEDELTA(pD->experience, experience, "u");

			if (pc.pos.x != pc2.pos.x || pc.pos.y != pc2.pos.y)
			{
				// snap droid(if on ground) to terrain level at x,y.
				if ((asPropulsionStats + pD->asBits[COMP_PROPULSION].nStat)->propulsionType != PROPULSION_TYPE_LIFT)  // if not airborne.
				{
					pD->pos.z = map_Height(pD->pos.x, pD->pos.y);
				}
			}

			// Doesn't cover all cases, but at least doesn't actively break stuff randomly.
			switch (pc.order)
			{
				case DORDER_MOVE:
					if (pc.order != pc2.order || pc.orderX != pc2.orderX || pc.orderY != pc2.orderY)
					{
						debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%d, %d).", pc.droidID, getDroidOrderName(pc2.order), getDroidOrderName(pc.order), pc.orderX, pc.orderY);
						// reroute the droid.
						orderDroidLoc(pD, pc.order, pc.orderX, pc.orderY, ModeImmediate);
					}
					break;
				case DORDER_ATTACK:
					if (pc.order != pc2.order || pc.targetID != pc2.targetID)
					{
						BASE_OBJECT *obj = IdToPointer(pc.targetID, ANYPLAYER);
						if (obj != NULL)
						{
							debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%u).", pc.droidID, getDroidOrderName(pc2.order), getDroidOrderName(pc.order), pc.targetID);
							// remote droid is attacking, not here tho!
							orderDroidObj(pD, pc.order, IdToPointer(pc.targetID, ANYPLAYER), ModeImmediate);
						}
						else
						{
							debug(LOG_SYNC, "Droid %u out of synch, would change order from %s to %s(%u), but can't find target.", pc.droidID, getDroidOrderName(pc2.order), getDroidOrderName(pc.order), pc.targetID);
						}
					}
					break;
				case DORDER_NONE:
				case DORDER_GUARD:
					if (pc.order != pc2.order)
					{
						DROID_ORDER_DATA sOrder;
						memset(&sOrder, 0, sizeof(DROID_ORDER_DATA));
						sOrder.order = pc.order;

						debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s.", pc.droidID, getDroidOrderName(pc2.order), getDroidOrderName(pc.order));
						turnOffMultiMsg(true);
						moveStopDroid(pD);
						orderDroidBase(pD, &sOrder);
						turnOffMultiMsg(false);
					}
					break;
				default:
					break;  // Don't know what to do, but at least won't be actively breaking anything.
			}

			MERGECOPY(pD->secondaryOrder, secondaryOrder, "u");  // The old code set this after changing orders, so doing that in case.
#undef MERGECOPY
#undef MERGEDELTA

			syncDebugDroid(pD, '>');

			// ...and repeat!
		}

	NETend();

	return true;
}
Exemplo n.º 19
0
// ////////////////////////////////////////////////////////////////////////////
// receive droid information form other players.
bool recvDroidInfo(NETQUEUE queue)
{
	NETbeginDecode(queue, GAME_DROIDINFO);
	{
		QueuedDroidInfo info;
		memset(&info, 0x00, sizeof(info));
		NETQueuedDroidInfo(&info);

		STRUCTURE_STATS *psStats = NULL;
		if (info.subType == LocOrder && (info.order == DORDER_BUILD || info.order == DORDER_LINEBUILD))
		{
			// Find structure target
			for (unsigned typeIndex = 0; typeIndex < numStructureStats; typeIndex++)
			{
				if (asStructureStats[typeIndex].ref == info.structRef)
				{
					psStats = asStructureStats + typeIndex;
					break;
				}
			}
		}

		switch (info.subType)
		{
			case ObjOrder:       syncDebug("Order=%s,%d(%d)", getDroidOrderName(info.order), info.destId, info.destType); break;
			case LocOrder:       syncDebug("Order=%s,(%d,%d)", getDroidOrderName(info.order), info.pos.x, info.pos.y); break;
			case SecondaryOrder: syncDebug("SecondaryOrder=%d,%08X", (int)info.secOrder, (int)info.secState); break;
		}

		DROID_ORDER_DATA sOrder = infoToOrderData(info, psStats);

		uint32_t num = 0;
		NETuint32_t(&num);

		for (unsigned n = 0; n < num; ++n)
		{
			// Get the next droid ID which is being given this order.
			uint32_t deltaDroidId = 0;
			NETuint32_t(&deltaDroidId);
			info.droidId += deltaDroidId;

			DROID *psDroid = IdToDroid(info.droidId, info.player);
			if (!psDroid)
			{
				debug(LOG_NEVER, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
				      queue.index, info.droidId, isHumanPlayer(info.player) ? "Human" : "AI", info.player);
				syncDebug("Droid %d missing", info.droidId);
				continue;  // Can't find the droid, so skip this droid.
			}

			CHECK_DROID(psDroid);

			syncDebugDroid(psDroid, '<');

			switch (info.subType)
			{
				case ObjOrder:
				case LocOrder:
					/*
					* If the current order not is a command order and we are not a
					* commander yet are in the commander group remove us from it.
					*/
					if (hasCommander(psDroid))
					{
						psDroid->psGroup->remove(psDroid);
					}

					if (sOrder.psObj != TargetMissing)  // Only do order if the target didn't die.
					{
						if (!info.add)
						{
							orderDroidListEraseRange(psDroid, 0, psDroid->listSize + 1);  // Clear all non-pending orders, plus the first pending order (which is probably the order we just received).
							orderDroidBase(psDroid, &sOrder);  // Execute the order immediately (even if in the middle of another order.
						}
						else
						{
							orderDroidAdd(psDroid, &sOrder);   // Add the order to the (non-pending) list. Will probably overwrite the corresponding pending order, assuming all pending orders were written to the list.
						}
					}
					break;
				case SecondaryOrder:
					// Set the droids secondary order
					turnOffMultiMsg(true);
					secondarySetState(psDroid, info.secOrder, info.secState);
					turnOffMultiMsg(false);
					break;
			}

			syncDebugDroid(psDroid, '>');

			CHECK_DROID(psDroid);
		}
	}
	NETend();

	return true;
}
Exemplo n.º 20
0
// ////////////////////////////////////////////////////////////////////////////
// put down a base plate and start droid building it!
BOOL recvBuildStarted(NETMSG *pMsg)
{
	//UDWORD			targetId,order,droidId,structId,x,z,y,structStat,player;
	UDWORD			targetId,order,droidId,structId,structStat;
	UWORD			x,z,y,player;
	STRUCTURE_STATS *psStats;
	DROID			*psDroid;
	UDWORD			typeindex,actionX,actionY;

	player = pMsg->body[0];					// decode message.
	NetGet(pMsg,1,structStat);
	NetGet(pMsg,5,x);
	NetGet(pMsg,7,y);
	NetGet(pMsg,11,droidId);
	NetGet(pMsg,15,structId);
	order = pMsg->body[19];
	NetGet(pMsg,20,targetId);
	NetGet(pMsg,24,z);
	for(typeindex=0;										// find structure target
	(typeindex<numStructureStats ) && (asStructureStats[typeindex].ref != structStat);
	typeindex++);  

	psStats = &asStructureStats[typeindex];
	
	if(IdToDroid(droidId,player, &psDroid))
	{
		if (getDroidDestination( (BASE_STATS *)psStats ,x,y, &actionX,&actionY))				
		{
			psDroid->order = order;
			if(psDroid->order == DORDER_LINEBUILD)
			{
				psDroid->order = DORDER_BUILD;
			}
			psDroid->orderX = x;
			psDroid->orderY = y;
			psDroid->psTarStats = (BASE_STATS *) psStats;
			if(targetId)
			{
				psDroid->psTarget = IdToPointer(targetId,ANYPLAYER);
			}
			else
			{
				psDroid->psTarget = 0;
			}

			if (IsStatExpansionModule(psStats))
			{
				setUpBuildModule(psDroid);
			}
			else
			{
				droidStartBuild(psDroid);
				psDroid->action = DACTION_BUILD;
			}
			
		}


		if (psDroid->psTarget)									//sync id's 
		{
			((STRUCTURE*)psDroid->psTarget)->id = structId; 
		}
	}

	// order droid to start building it.
	return TRUE;
}