示例#1
0
bool updateScripts()
{
	// Update gameTime
	for (int i = 0; i < scripts.size(); ++i)
	{
		QScriptEngine *engine = scripts.at(i);

		engine->globalObject().setProperty("gameTime", gameTime, QScriptValue::ReadOnly | QScriptValue::Undeletable);
	}
	// Weed out dead timers
	for (int i = 0; i < timers.count(); )
	{
		const timerNode node = timers.at(i);
		if (node.type == TIMER_ONESHOT_DONE || (node.baseobj > 0 && !IdToPointer(node.baseobj, node.player)))
		{
			timers.removeAt(i);
		}
		else
		{
			i++;
		}
	}
	// Check for timers, and run them if applicable.
	// TODO - load balancing
	QList<timerNode> runlist; // make a new list here, since we might trample all over the timer list during execution
	QList<timerNode>::iterator iter;
	// Weed out dead timers
	for (iter = timers.begin(); iter != timers.end(); iter++)
	{
		if (iter->frameTime <= gameTime)
		{
			iter->frameTime = iter->ms + gameTime;	// update for next invokation
			if (iter->type == TIMER_ONESHOT_READY)
			{
				iter->type = TIMER_ONESHOT_DONE; // unless there is none
			}
			runlist.append(*iter);
		}
	}
	for (iter = runlist.begin(); iter != runlist.end(); iter++)
	{
		QScriptValueList args;
		if (iter->baseobj > 0)
		{
			args += convObj(IdToPointer(iter->baseobj, iter->player), iter->engine);
		}
		callFunction(iter->engine, iter->function, args, true);
	}
	return true;
}
示例#2
0
// recv lassat info on the receiving end.
BOOL recvLasSat(NETQUEUE queue)
{
	BASE_OBJECT	*psObj;
	UBYTE		player,targetplayer;
	STRUCTURE	*psStruct;
	uint32_t	id,targetid;

	// TODO Add some kind of checking, so that things don't get lasatted by bunkers.
	NETbeginDecode(queue, GAME_LASSAT);
		NETuint8_t(&player);
		NETuint32_t(&id);
		NETuint32_t(&targetid);
		NETuint8_t(&targetplayer);
	NETend();

	psStruct = IdToStruct (id, player);
	psObj	 = IdToPointer(targetid, targetplayer);

	if (psStruct && psObj)
	{
		// Give enemy no quarter, unleash the lasat
		proj_SendProjectile(&psStruct->asWeaps[0], NULL, player, psObj->pos, psObj, true, 0);
		psStruct->asWeaps[0].lastFired = gameTime;

		// Play 5 second countdown message
		audio_QueueTrackPos( ID_SOUND_LAS_SAT_COUNTDOWN, psObj->pos.x, psObj->pos.y, psObj->pos.z);
	}

	return true;
}
示例#3
0
//-- \subsection{bind(function, object[, player])}
//-- Bind a function call to an object. The function is called before the 
//-- object is destroyed. The function to run is the first parameter, and it 
//-- \underline{must be quoted}, otherwise the function will be inlined. The
//-- second argument is the object to bind to. A third, optional player parameter
//-- may be passed, which may be used for filtering, depending on the object type.
//-- \emph{NOTE: This function is under construction and is subject to total change!}
static QScriptValue js_bind(QScriptContext *context, QScriptEngine *engine)
{
	SCRIPT_ASSERT(context, context->argument(0).isString(), "Bound functions must be quoted");
	bindNode node;
	QScriptValue objv = context->argument(1);
	node.type = objv.property("type").toInt32();
	node.player = -1;
	node.funcName = context->argument(0).toString();
	node.engine = engine;
	node.player = objv.property("player").toInt32();
	node.id = objv.property("id").toInt32();
	if (node.type == OBJ_DROID || node.type == OBJ_STRUCTURE || node.type == OBJ_FEATURE)
	{
		BASE_OBJECT *psObj = IdToPointer(node.id, node.player);
		if (psObj && !psObj->died)
		{
			bindings.insert(node.id, node);
		}
	}
	else
	{
		debug(LOG_ERROR, "Trying to bind to illegal object type");
	}
	return QScriptValue();
}
// recv lassat info on the receiving end.
BOOL recvLasSat()
{
    BASE_OBJECT	*psObj;
    UBYTE		player,targetplayer;
    STRUCTURE	*psStruct;
    uint32_t	id,targetid;

    NETbeginDecode(NET_LASSAT);
    NETuint8_t(&player);
    NETuint32_t(&id);
    NETuint32_t(&targetid);
    NETuint8_t(&targetplayer);
    NETend();

    psStruct = IdToStruct (id, player);
    psObj	 = IdToPointer(targetid, targetplayer);

    if (psStruct && psObj)
    {
        // Give enemy no quarter, unleash the lasat
        proj_SendProjectile(&psStruct->asWeaps[0], NULL, player, psObj->pos, psObj, true, 0);

        // Play 5 second countdown message
        audio_QueueTrackPos( ID_SOUND_LAS_SAT_COUNTDOWN, psObj->pos.x, psObj->pos.y, psObj->pos.z);
    }

    return true;
}
示例#5
0
// recv lassat info on the receiving end.
BOOL recvLasSat(NETMSG *pMsg)
{
	BASE_OBJECT	*psObj;
	UBYTE		player,targetplayer;
	STRUCTURE	*psStruct;
	UDWORD		id,tid;

	NetGet(pMsg,0,player);
	NetGet(pMsg,1,id);
	NetGet(pMsg,5,tid);
	NetGet(pMsg,9,targetplayer);

	psStruct = IdToStruct (id ,player);
	psObj	 = IdToPointer(tid,targetplayer);

	if(psStruct && psObj)
	{
		proj_SendProjectile(&psStruct->asWeaps[0], NULL, player, psObj->x, 
            psObj->y, psObj->z, psObj, TRUE);
        //play 5 second countdown message
		audio_QueueTrackPos( ID_SOUND_LAS_SAT_COUNTDOWN, psObj->x, psObj->y, 
            psObj->z );
	}

	return TRUE;
}
示例#6
0
// recv lassat info on the receiving end.
bool recvLasSat(NETQUEUE queue)
{
	BASE_OBJECT	*psObj;
	UBYTE		player, targetplayer;
	STRUCTURE	*psStruct;
	uint32_t	id, targetid;

	NETbeginDecode(queue, GAME_LASSAT);
	NETuint8_t(&player);
	NETuint32_t(&id);
	NETuint32_t(&targetid);
	NETuint8_t(&targetplayer);
	NETend();

	psStruct = IdToStruct(id, player);
	psObj	 = IdToPointer(targetid, targetplayer);
	if (psStruct && !canGiveOrdersFor(queue.index, psStruct->player))
	{
		syncDebug("Wrong player.");
		return false;
	}

	if (psStruct && psObj && psStruct->pStructureType->psWeapStat[0]->weaponSubClass == WSC_LAS_SAT)
	{
		// Lassats have just one weapon
		unsigned firePause = weaponFirePause(&asWeaponStats[psStruct->asWeaps[0].nStat], player);
		unsigned damLevel = PERCENT(psStruct->body, structureBody(psStruct));

		if (damLevel < HEAVY_DAMAGE_LEVEL)
		{
			firePause += firePause;
		}

		if (isHumanPlayer(player) && gameTime - psStruct->asWeaps[0].lastFired <= firePause)
		{
			/* Too soon to fire again */
			return true ^ false;  // Return value meaningless and ignored.
		}

		// Give enemy no quarter, unleash the lasat
		proj_SendProjectile(&psStruct->asWeaps[0], NULL, player, psObj->pos, psObj, true, 0);
		psStruct->asWeaps[0].lastFired = gameTime;
		psStruct->asWeaps[0].ammo = 1; // abducting this field for keeping track of triggers

		// Play 5 second countdown message
		audio_QueueTrackPos(ID_SOUND_LAS_SAT_COUNTDOWN, psObj->pos.x, psObj->pos.y, psObj->pos.z);
	}

	return true;
}
示例#7
0
void scriptRemoveObject(const BASE_OBJECT *psObj)
{
	for (QHash<int, bindNode>::iterator i = bindings.find(psObj->id); i != bindings.end(); i++)
	{
		int id = i.key();
		bindNode node = i.value();
		BASE_OBJECT *psObj = IdToPointer(id, node.player);
		if (psObj && !psObj->died)
		{
			QScriptValueList args;
			args += convMax(psObj, node.engine);
			callFunction(node.engine, node.funcName, args);
		}
		bindings.erase(i);
	}
}
示例#8
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;
}
示例#9
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;
}
// ////////////////////////////////////////////////////////////////////////////
// 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;
}