/** * Set the new destination of the unit. * * Stack: 1 - An encoded index where to move to. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_SetDestination(ScriptEngine *script) { Unit *u; uint16 encoded; u = g_scriptCurrentUnit; encoded = STACK_PEEK(1); if (encoded == 0 || !Tools_Index_IsValid(encoded)) { u->targetMove = 0; return 0; } if (u->o.type == UNIT_HARVESTER) { Structure *s; s = Tools_Index_GetStructure(encoded); if (s == NULL) { u->targetMove = encoded; u->route[0] = 0xFF; return 0; } if (s->o.script.variables[4] != 0) return 0; } Unit_SetDestination(u, encoded); return 0; }
/** * Unknown function 2BD5. * * Stack: *none*. * * @param script The script engine to operate on. * @return ??. */ uint16 Script_Unit_Unknown2BD5(ScriptEngine *script) { Unit *u; VARIABLE_NOT_USED(script); u = g_scriptCurrentUnit; switch (Tools_Index_GetType(u->o.script.variables[4])) { case IT_UNIT: { Unit *u2; u2 = Tools_Index_GetUnit(u->o.script.variables[4]); if (Tools_Index_Encode(u->o.index, IT_UNIT) == u2->o.script.variables[4] && u2->o.houseID == u->o.houseID) return 1; u2->targetMove = 0; } break; case IT_STRUCTURE: { Structure *s; s = Tools_Index_GetStructure(u->o.script.variables[4]); if (Tools_Index_Encode(u->o.index, IT_UNIT) == s->o.script.variables[4] && s->o.houseID == u->o.houseID) return 1; } break; default: break; } Object_Script_Variable4_Clear(&u->o); return 0; }
/** * Gets the distance from the given object to the given encoded index. * @param o The object. * @param encoded The encoded index. * @return The distance. */ uint16 Object_GetDistanceToEncoded(Object* o, uint16 encoded) { Structure* s; tile32 position; s = Tools_Index_GetStructure(encoded); if (s != NULL) { uint16 packed; position = s->o.position; packed = Tile_PackTile(position); packed += g_table_structure_layoutEdgeTiles[g_table_structureInfo[o->type].layout][(Orientation_256To8(Tile_GetDirection(o->position, position)) + 4) & 7]; position = Tile_UnpackTile(packed); } else { position = Tools_Index_GetTile(encoded); } return Tile_GetDistance(o->position, position); }
/** * Move the unit to the first available structure it can find of the required * type. * * Stack: 1 - Type of structure. * * @param script The script engine to operate on. * @return An encoded structure index. */ uint16 Script_Unit_MoveToStructure(ScriptEngine *script) { Unit *u; PoolFindStruct find; u = g_scriptCurrentUnit; if (u->o.linkedID != 0xFF) { Structure *s; s = Tools_Index_GetStructure(Unit_Get_ByIndex(u->o.linkedID)->originEncoded); if (s != NULL && s->state == STRUCTURE_STATE_IDLE && s->o.script.variables[4] == 0) { uint16 encoded; encoded = Tools_Index_Encode(s->o.index, IT_STRUCTURE); Object_Script_Variable4_Link(Tools_Index_Encode(u->o.index, IT_UNIT), encoded); u->targetMove = u->o.script.variables[4]; return encoded; } } find.houseID = Unit_GetHouseID(u); find.index = 0xFFFF; find.type = STACK_PEEK(1); while (true) { Structure *s; uint16 encoded; s = Structure_Find(&find); if (s == NULL) break; if (s->state != STRUCTURE_STATE_IDLE) continue; if (s->o.script.variables[4] != 0) continue; encoded = Tools_Index_Encode(s->o.index, IT_STRUCTURE); Object_Script_Variable4_Link(Tools_Index_Encode(u->o.index, IT_UNIT), encoded); u->targetMove = encoded; return encoded; } return 0; }
/** * Get the priority a target has for the current unit. * * Stack: 1 - The encoded target. * * @param script The script engine to operate on. * @return The priority of the target. */ uint16 Script_Unit_GetTargetPriority(ScriptEngine *script) { Unit *u; Unit *target; Structure *s; uint16 encoded; u = g_scriptCurrentUnit; encoded = STACK_PEEK(1); target = Tools_Index_GetUnit(encoded); if (target != NULL) return Unit_GetTargetUnitPriority(u, target); s = Tools_Index_GetStructure(encoded); if (s == NULL) return 0; return Unit_GetTargetStructurePriority(u, s); }
/** * 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; } }
/** * 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; }