Example #1
0
/**
 * Unknown function 0C5A.
 *
 * Stack: *none*
 *
 * @param script The script engine to operate on.
 * @return unknown.
 */
uint16 Script_Structure_Unknown0C5A(ScriptEngine *script)
{
	tile32 tile;
	Structure *s;
	Unit *u;
	uint16 position;

	VARIABLE_NOT_USED(script);

	s = g_scriptCurrentStructure;

	if (s->o.linkedID == 0xFF) return 0;

	u = Unit_Get_ByIndex(s->o.linkedID);

	if (g_table_unitInfo[u->o.type].movementType == MOVEMENT_WINGER && Unit_SetPosition(u, s->o.position)) {
		s->o.linkedID = u->o.linkedID;
		u->o.linkedID = 0xFF;

		if (s->o.linkedID == 0xFF) Structure_SetState(s, STRUCTURE_STATE_IDLE);
		Object_Script_Variable4_Clear(&s->o);

		if (s->o.houseID == g_playerHouseID) Sound_Output_Feedback(g_playerHouseID + 49);

		return 1;
	}

	position = Structure_FindFreePosition(s, u->o.type == UNIT_HARVESTER);
	if (position == 0) return 0;

	u->o.seenByHouses |= s->o.seenByHouses;

	tile = Tile_Center(Tile_UnpackTile(position));

	if (!Unit_SetPosition(u, tile)) return 0;

	s->o.linkedID = u->o.linkedID;
	u->o.linkedID = 0xFF;

	Unit_SetOrientation(u, Tile_GetDirection(s->o.position, u->o.position) & 0xE0, true, 0);
	Unit_SetOrientation(u, u->orientation[0].current, true, 1);

	if (u->o.houseID == g_playerHouseID && u->o.type == UNIT_HARVESTER) {
		GUI_DisplayHint(STR_SEARCH_FOR_SPICE_FIELDS_TO_HARVEST, 0x6A);
	}

	if (s->o.linkedID == 0xFF) Structure_SetState(s, STRUCTURE_STATE_IDLE);
	Object_Script_Variable4_Clear(&s->o);

	if (s->o.houseID != g_playerHouseID) return 1;
	if (s->o.type == STRUCTURE_REPAIR) return 1;

	Sound_Output_Feedback(g_playerHouseID + ((u->o.type == UNIT_HARVESTER) ? 68 : 30));

	return 1;
}
Example #2
0
/**
 * Refine spice in the current structure.
 *
 * Stack: *none*
 *
 * @param script The script engine to operate on.
 * @return 0 if there is no spice to refine, otherwise 1.
 */
uint16 Script_Structure_RefineSpice(ScriptEngine *script)
{
	const StructureInfo *si;
	Structure *s;
	Unit *u;
	House *h;
	uint16 harvesterStep, creditsStep;

	VARIABLE_NOT_USED(script);

	s = g_scriptCurrentStructure;

	if (s->o.linkedID == 0xFF) {
		Structure_SetState(s, STRUCTURE_STATE_IDLE);
		return 0;
	}

	u = Unit_Get_ByIndex(s->o.linkedID);
	si = &g_table_structureInfo[s->o.type];

	harvesterStep = (s->o.hitpoints * 256 / si->o.hitpoints) * 3 / 256;

	if (u->amount < harvesterStep) harvesterStep = u->amount;
	if (u->amount != 0 && harvesterStep < 1) harvesterStep = 1;
	if (harvesterStep == 0) return 0;

	creditsStep = 7;
	if (u->o.houseID != g_playerHouseID) {
		creditsStep += (Tools_Random_256() % 4) - 1;
	}

	creditsStep *= harvesterStep;

	if (House_AreAllied(g_playerHouseID, s->o.houseID)) {
		g_scenario.harvestedAllied += creditsStep;
		if (g_scenario.harvestedAllied > 65000) g_scenario.harvestedAllied = 65000;
	} else {
		g_scenario.harvestedEnemy += creditsStep;
		if (g_scenario.harvestedEnemy > 65000) g_scenario.harvestedEnemy = 65000;
	}

	h = House_Get_ByIndex(s->o.houseID);
	h->credits += creditsStep;
	u->amount -= harvesterStep;

	if (u->amount == 0) u->o.flags.s.inTransport = false;
	s->o.script.delay = 6;
	return 1;
}
Example #3
0
/**
 * Set in a safe way the new value for variable4.
 * @param o The Object to set variable4 for.
 * @param index The encoded index to set it to.
 */
void Object_Script_Variable4_Set(Object* o, uint16 encoded)
{
	StructureInfo* si;
	Structure* s;

	if (o == NULL)
		return;

	o->script.variables[4] = encoded;

	if (o->flags.s.isUnit)
		return;

	si = &g_table_structureInfo[o->type];
	if (!si->o.flags.busyStateIsIncoming)
		return;

	s = (Structure *)o;
	if (Structure_GetLinkedUnit(s) != NULL)
		return;

	Structure_SetState(s, (encoded == 0) ? STRUCTURE_STATE_IDLE : STRUCTURE_STATE_BUSY);
}
Example #4
0
/**
 * Set the state for the current structure.
 *
 * Stack: 1 - The state.
 *
 * @param script The script engine to operate on.
 * @return The value 0. Always.
 */
uint16 Script_Structure_SetState(ScriptEngine *script)
{
	Structure *s;
	int16 state;

	s = g_scriptCurrentStructure;
	state = STACK_PEEK(1);

	if (state == STRUCTURE_STATE_DETECT) {
		if (s->o.linkedID == 0xFF) {
			state = STRUCTURE_STATE_IDLE;
		} else {
			if (s->countDown == 0) {
				state = STRUCTURE_STATE_READY;
			} else {
				state = STRUCTURE_STATE_BUSY;
			}
		}
	}

	Structure_SetState(s, state);

	return 0;
}
Example #5
0
/**
 * Prepare the map (after loading scenario or savegame). Does some basic
 *  sanity-check and corrects stuff all over the place.
 */
void Game_Prepare(void)
{
	PoolFindStruct find;
	uint16 oldSelectionType;
	Tile *t;
	int i;

	g_validateStrictIfZero++;

	oldSelectionType = g_selectionType;
	g_selectionType = SELECTIONTYPE_MENTAT;

	Structure_Recount();
	Unit_Recount();
	Team_Recount();

	t = &g_map[0];
	for (i = 0; i < 64 * 64; i++, t++) {
		Structure *s;
		Unit *u;

		u = Unit_Get_ByPackedTile(i);
		s = Structure_Get_ByPackedTile(i);

		if (u == NULL || !u->o.flags.s.used) t->hasUnit = false;
		if (s == NULL || !s->o.flags.s.used) t->hasStructure = false;
		if (t->isUnveiled) Map_UnveilTile(i, g_playerHouseID);
	}

	find.houseID = HOUSE_INVALID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		Unit *u;

		u = Unit_Find(&find);
		if (u == NULL) break;

		if (u->o.flags.s.isNotOnMap) continue;

		Unit_RemoveFog(u);
		Unit_UpdateMap(1, u);
	}

	find.houseID = HOUSE_INVALID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		Structure *s;

		s = Structure_Find(&find);
		if (s == NULL) break;
		if (s->o.type == STRUCTURE_SLAB_1x1 || s->o.type == STRUCTURE_SLAB_2x2 || s->o.type == STRUCTURE_WALL) continue;

		if (s->o.flags.s.isNotOnMap) continue;

		Structure_RemoveFog(s);

		if (s->o.type == STRUCTURE_STARPORT && s->o.linkedID != 0xFF) {
			Unit *u = Unit_Get_ByIndex(s->o.linkedID);

			if (!u->o.flags.s.used || !u->o.flags.s.isNotOnMap) {
				s->o.linkedID = 0xFF;
				s->countDown = 0;
			} else {
				Structure_SetState(s, STRUCTURE_STATE_READY);
			}
		}

		Script_Load(&s->o.script, s->o.type);

		if (s->o.type == STRUCTURE_PALACE) {
			House_Get_ByIndex(s->o.houseID)->palacePosition = s->o.position;
		}

		if ((House_Get_ByIndex(s->o.houseID)->palacePosition.x != 0) || (House_Get_ByIndex(s->o.houseID)->palacePosition.y != 0)) continue;
		House_Get_ByIndex(s->o.houseID)->palacePosition = s->o.position;
	}

	find.houseID = HOUSE_INVALID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		House *h;

		h = House_Find(&find);
		if (h == NULL) break;

		h->structuresBuilt = Structure_GetStructuresBuilt(h);
		House_UpdateCreditsStorage((uint8)h->index);
		House_CalculatePowerAndCredit(h);
	}

	GUI_Palette_CreateRemap(g_playerHouseID);

	Map_SetSelection(g_selectionPosition);

	if (g_structureActiveType != 0xFFFF) {
		Map_SetSelectionSize(g_table_structureInfo[g_structureActiveType].layout);
	} else {
		Structure *s = Structure_Get_ByPackedTile(g_selectionPosition);

		if (s != NULL) Map_SetSelectionSize(g_table_structureInfo[s->o.type].layout);
	}

	Voice_LoadVoices(g_playerHouseID);

	g_tickHousePowerMaintenance = max(g_timerGame + 70, g_tickHousePowerMaintenance);
	g_viewport_forceRedraw = true;
	g_playerCredits = 0xFFFF;

	g_selectionType = oldSelectionType;
	g_validateStrictIfZero--;
}
Example #6
0
/**
 * Pickup a unit (either from structure or on the map). The unit that does the
 *  picking up returns the unit to his last position.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return The value 0. Always.
 */
uint16 Script_Unit_Pickup(ScriptEngine *script)
{
	Unit *u;

	VARIABLE_NOT_USED(script);

	u = g_scriptCurrentUnit;

	if (u->o.linkedID != 0xFF) return 0;

	switch (Tools_Index_GetType(u->targetMove)) {
		case IT_STRUCTURE: {
			Structure *s;
			Unit *u2;

			s = Tools_Index_GetStructure(u->targetMove);

			/* There was nothing to pickup here */
			if (s->state != STRUCTURE_STATE_READY) {
				Object_Script_Variable4_Clear(&u->o);
				u->targetMove = 0;
				return 0;
			}

			u->o.flags.s.inTransport = true;

			Object_Script_Variable4_Clear(&u->o);
			u->targetMove = 0;

			u2 = Unit_Get_ByIndex(s->o.linkedID);

			/* Pickup the unit */
			u->o.linkedID = u2->o.index & 0xFF;
			s->o.linkedID = u2->o.linkedID;
			u2->o.linkedID = 0xFF;

			if (s->o.linkedID == 0xFF) Structure_SetState(s, STRUCTURE_STATE_IDLE);

			/* Check if the unit has a return-to position or try to find spice in case of a harvester */
			if (u2->targetLast.tile != 0) {
				u->targetMove = Tools_Index_Encode(Tile_PackTile(u2->targetLast), IT_TILE);
			} else if (u2->o.type == UNIT_HARVESTER && Unit_GetHouseID(u2) != g_playerHouseID) {
				u->targetMove = Tools_Index_Encode(Map_SearchSpice(Tile_PackTile(u->o.position), 20), IT_TILE);
			}

			Unit_UpdateMap(2, u);

			return 1;
		}

		case IT_UNIT: {
			Unit *u2;
			Structure *s = NULL;
			PoolFindStruct find;
			int16 minDistance = 0;

			u2 = Tools_Index_GetUnit(u->targetMove);

			if (!u2->o.flags.s.allocated) return 0;

			find.houseID = Unit_GetHouseID(u);
			find.index   = 0xFFFF;
			find.type    = 0xFFFF;

			/* Find closest refinery / repair station */
			while (true) {
				Structure *s2;
				int16 distance;

				s2 = Structure_Find(&find);
				if (s2 == NULL) break;

				distance = Tile_GetDistanceRoundedUp(s2->o.position, u->o.position);

				if (u2->o.type == UNIT_HARVESTER) {
					if (s2->o.type != STRUCTURE_REFINERY || s2->state != STRUCTURE_STATE_IDLE || s2->o.script.variables[4] != 0) continue;
					if (minDistance != 0 && distance >= minDistance) break;
					minDistance = distance;
					s = s2;
					break;
				}

				if (s2->o.type != STRUCTURE_REPAIR || s2->state != STRUCTURE_STATE_IDLE || s2->o.script.variables[4] != 0) continue;

				if (minDistance != 0 && distance >= minDistance) continue;
				minDistance = distance;
				s = s2;
			}

			if (s == NULL) return 0;

			/* Deselect the unit as it is about to be picked up */
			if (u2 == g_unitSelected) Unit_Select(NULL);

			/* Pickup the unit */
			u->o.linkedID = u2->o.index & 0xFF;
			u->o.flags.s.inTransport = true;

			Unit_UpdateMap(0, u2);

			Unit_Hide(u2);

			/* Set where we are going to */
			Object_Script_Variable4_Link(Tools_Index_Encode(u->o.index, IT_UNIT), Tools_Index_Encode(s->o.index, IT_STRUCTURE));
			u->targetMove = u->o.script.variables[4];

			Unit_UpdateMap(2, u);

			if (u2->o.type != UNIT_HARVESTER) return 0;

			/* Check if we want to return to this spice field later */
			if (Map_SearchSpice(Tile_PackTile(u2->o.position), 2) == 0) {
				u2->targetPreLast.tile = 0;
				u2->targetLast.tile    = 0;
			}

			return 0;
		}

		default: return 0;
	}
}
Example #7
0
/**
 * Delivery of transport, either to structure or to a tile.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return One if delivered, zero otherwise..
 */
uint16 Script_Unit_TransportDeliver(ScriptEngine *script)
{
	Unit *u;
	Unit *u2;

	VARIABLE_NOT_USED(script);

	u = g_scriptCurrentUnit;

	if (u->o.linkedID == 0xFF) return 0;
	if (Tools_Index_GetType(u->targetMove) == IT_UNIT) return 0;

	if (Tools_Index_GetType(u->targetMove) == IT_STRUCTURE) {
		const StructureInfo *si;
		Structure *s;

		s = Tools_Index_GetStructure(u->targetMove);
		si = &g_table_structureInfo[s->o.type];

		if (s->o.type == STRUCTURE_STARPORT) {
			uint16 ret = 0;

			if (s->state == STRUCTURE_STATE_BUSY) {
				s->o.linkedID = u->o.linkedID;
				u->o.linkedID = 0xFF;
				u->o.flags.s.inTransport = false;
				u->amount = 0;

				Unit_UpdateMap(2, u);

				Voice_PlayAtTile(24, u->o.position);

				Structure_SetState(s, STRUCTURE_STATE_READY);

				ret = 1;
			}

			Object_Script_Variable4_Clear(&u->o);
			u->targetMove = 0;

			return ret;
		}

		if ((s->state == STRUCTURE_STATE_IDLE || (si->o.flags.busyStateIsIncoming && s->state == STRUCTURE_STATE_BUSY)) && s->o.linkedID == 0xFF) {
			Voice_PlayAtTile(24, u->o.position);

			Unit_EnterStructure(Unit_Get_ByIndex(u->o.linkedID), s);

			Object_Script_Variable4_Clear(&u->o);
			u->targetMove = 0;

			u->o.linkedID = 0xFF;
			u->o.flags.s.inTransport = false;
			u->amount = 0;

			Unit_UpdateMap(2, u);

			return 1;
		}

		Object_Script_Variable4_Clear(&u->o);
		u->targetMove = 0;

		return 0;
	}

	if (!Map_IsValidPosition(Tile_PackTile(Tile_Center(u->o.position)))) return 0;

	u2 = Unit_Get_ByIndex(u->o.linkedID);

	if (!Unit_SetPosition(u2, Tile_Center(u->o.position))) return 0;

	if (u2->o.houseID == g_playerHouseID) {
		Voice_PlayAtTile(24, u->o.position);
	}

	Unit_SetOrientation(u2, u->orientation[0].current, true, 0);
	Unit_SetOrientation(u2, u->orientation[0].current, true, 1);
	Unit_SetSpeed(u2, 0);

	u->o.linkedID = u2->o.linkedID;
	u2->o.linkedID = 0xFF;

	if (u->o.linkedID != 0xFF) return 1;

	u->o.flags.s.inTransport = false;

	Object_Script_Variable4_Clear(&u->o);
	u->targetMove = 0;

	return 1;
}