/** * 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; }
/** * Loop over all houses, preforming various of tasks. */ void GameLoop_House(void) { PoolFindStruct find; House *h = NULL; bool tickHouse = false; bool tickPowerMaintenance = false; bool tickStarport = false; bool tickReinforcement = false; bool tickMissileCountdown = false; bool tickStarportAvailability = false; if (g_debugScenario) return; if (s_tickHouseHouse <= g_timerGame) { tickHouse = true; s_tickHouseHouse = g_timerGame + 900; } if (g_tickHousePowerMaintenance <= g_timerGame) { tickPowerMaintenance = true; g_tickHousePowerMaintenance = g_timerGame + 10800; } if (s_tickHouseStarport <= g_timerGame) { tickStarport = true; s_tickHouseStarport = g_timerGame + 180; } if (s_tickHouseReinforcement <= g_timerGame) { tickReinforcement = true; s_tickHouseReinforcement = g_timerGame + (g_debugGame ? 60 : 600); } if (s_tickHouseMissileCountdown <= g_timerGame) { tickMissileCountdown = true; s_tickHouseMissileCountdown = g_timerGame + 60; } if (s_tickHouseStarportAvailability <= g_timerGame) { tickStarportAvailability = true; s_tickHouseStarportAvailability = g_timerGame + 1800; } if (tickMissileCountdown && g_houseMissileCountdown != 0) { g_houseMissileCountdown--; Sound_Output_Feedback(g_houseMissileCountdown + 41); if (g_houseMissileCountdown == 0) Unit_LaunchHouseMissile(Map_FindLocationTile(4, g_playerHouseID)); } if (tickStarportAvailability) { uint16 type; /* Pick a random unit to increase starport availability */ type = Tools_RandomLCG_Range(0, UNIT_MAX - 1); /* Increase how many of this unit is available via starport by one */ if (g_starportAvailable[type] != 0 && g_starportAvailable[type] < 10) { if (g_starportAvailable[type] == -1) { g_starportAvailable[type] = 1; } else { g_starportAvailable[type]++; } } } if (tickReinforcement) { Unit *nu = NULL; int i; for (i = 0; i < 16; i++) { uint16 locationID; bool deployed; Unit *u; if (g_scenario.reinforcement[i].unitID == UNIT_INDEX_INVALID) continue; if (g_scenario.reinforcement[i].timeLeft == 0) continue; if (--g_scenario.reinforcement[i].timeLeft != 0) continue; u = Unit_Get_ByIndex(g_scenario.reinforcement[i].unitID); locationID = g_scenario.reinforcement[i].locationID; deployed = false; if (locationID >= 4) { if (nu == NULL) { nu = Unit_Create(UNIT_INDEX_INVALID, UNIT_CARRYALL, u->o.houseID, Tile_UnpackTile(Map_FindLocationTile(Tools_Random_256() & 3, u->o.houseID)), 100); if (nu != NULL) { nu->o.flags.s.byScenario = true; Unit_SetDestination(nu, Tools_Index_Encode(Map_FindLocationTile(locationID, u->o.houseID), IT_TILE)); } } if (nu != NULL) { u->o.linkedID = nu->o.linkedID; nu->o.linkedID = (uint8)u->o.index; nu->o.flags.s.inTransport = true; g_scenario.reinforcement[i].unitID = UNIT_INDEX_INVALID; deployed = true; } else { /* Failed to create carry-all, try again in a short moment */ g_scenario.reinforcement[i].timeLeft = 1; } } else { deployed = Unit_SetPosition(u, Tile_UnpackTile(Map_FindLocationTile(locationID, u->o.houseID))); } if (deployed && g_scenario.reinforcement[i].repeat != 0) { tile32 tile; tile.x = 0xFFFF; tile.y = 0xFFFF; g_validateStrictIfZero++; u = Unit_Create(UNIT_INDEX_INVALID, u->o.type, u->o.houseID, tile, 0); g_validateStrictIfZero--; if (u != NULL) { g_scenario.reinforcement[i].unitID = u->o.index; g_scenario.reinforcement[i].timeLeft = g_scenario.reinforcement[i].timeBetween; } } } } find.houseID = HOUSE_INVALID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { h = House_Find(&find); if (h == NULL) break; if (tickHouse) { /* ENHANCEMENT -- Originally this code was outside the house loop, which seems very odd. * This problem is considered to be so bad, that the original code has been removed. */ if (h->index != g_playerHouseID) { if (h->creditsStorage < h->credits) { h->credits = h->creditsStorage; } } else { uint16 maxCredits = max(h->creditsStorage, g_playerCreditsNoSilo); if (h->credits > maxCredits) { h->credits = maxCredits; GUI_DisplayText(String_Get_ByIndex(STR_INSUFFICIENT_SPICE_STORAGE_AVAILABLE_SPICE_IS_LOST), 1); } } if (h->index == g_playerHouseID) { if (h->creditsStorage > g_playerCreditsNoSilo) { g_playerCreditsNoSilo = 0; } if (g_playerCreditsNoSilo == 0 && g_campaignID > 1 && h->credits != 0) { if (h->creditsStorage != 0 && ((h->credits * 256 / h->creditsStorage) > 200)) { GUI_DisplayText(String_Get_ByIndex(STR_SPICE_STORAGE_CAPACITY_LOW_BUILD_SILOS), 0); } } if (h->credits < 100 && g_playerCreditsNoSilo != 0) { GUI_DisplayText(String_Get_ByIndex(STR_CREDITS_ARE_LOW_HARVEST_SPICE_FOR_MORE_CREDITS), 0); } } } if (tickHouse) House_EnsureHarvesterAvailable((uint8)h->index); if (tickStarport && h->starportLinkedID != UNIT_INDEX_INVALID) { Unit *u = NULL; h->starportTimeLeft--; if ((int16)h->starportTimeLeft < 0) h->starportTimeLeft = 0; if (h->starportTimeLeft == 0) { Structure *s; s = Structure_Get_ByIndex(g_structureIndex); if (s->o.type == STRUCTURE_STARPORT && s->o.houseID == h->index) { u = Unit_CreateWrapper((uint8)h->index, UNIT_FRIGATE, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); } else { PoolFindStruct find2; find2.houseID = h->index; find2.index = 0xFFFF; find2.type = STRUCTURE_STARPORT; while (true) { s = Structure_Find(&find2); if (s == NULL) break; if (s->o.linkedID != 0xFF) continue; u = Unit_CreateWrapper((uint8)h->index, UNIT_FRIGATE, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); break; } } if (u != NULL) { u->o.linkedID = (uint8)h->starportLinkedID; h->starportLinkedID = UNIT_INDEX_INVALID; u->o.flags.s.inTransport = true; Sound_Output_Feedback(38); } h->starportTimeLeft = (u != NULL) ? g_table_houseInfo[h->index].starportDeliveryTime : 1; } } if (tickHouse) { House_CalculatePowerAndCredit(h); Structure_CalculateHitpointsMax(h); if (h->timerUnitAttack != 0) h->timerUnitAttack--; if (h->timerSandwormAttack != 0) h->timerSandwormAttack--; if (h->timerStructureAttack != 0) h->timerStructureAttack--; if (h->harvestersIncoming > 0 && Unit_CreateWrapper((uint8)h->index, UNIT_HARVESTER, 0) != NULL) h->harvestersIncoming--; } if (tickPowerMaintenance) { uint16 powerMaintenanceCost = (h->powerUsage / 32) + 1; h->credits -= min(h->credits, powerMaintenanceCost); } } }
/** * 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; }