/** * Move the Unit to the target, and keep repeating this function till we * arrived there. When closing in on the target it will slow down the Unit. * It is wise to only use this function on Carry-Alls. * * Stack: *none*. * * @param script The script engine to operate on. * @return 1 if arrived, 0 if still busy. */ uint16 Script_Unit_MoveToTarget(ScriptEngine *script) { Unit *u; uint16 delay; tile32 tile; uint16 distance; int8 orientation; int16 diff; u = g_scriptCurrentUnit; if (u->targetMove == 0) return 0; tile = Tools_Index_GetTile(u->targetMove); distance = Tile_GetDistance(u->o.position, tile); if ((int16)distance < 128) { Unit_SetSpeed(u, 0); u->o.position.s.x += clamp((int16)(tile.s.x - u->o.position.s.x), -16, 16); u->o.position.s.y += clamp((int16)(tile.s.y - u->o.position.s.y), -16, 16); Unit_UpdateMap(2, u); if ((int16)distance < 32) return 1; script->delay = 2; script->script--; return 0; } orientation = Tile_GetDirection(u->o.position, tile); Unit_SetOrientation(u, orientation, false, 0); diff = abs(orientation - u->orientation[0].current); if (diff > 128) diff = 256 - diff; Unit_SetSpeed(u, (Tools_AdjustToGameSpeed(min(distance / 8, 255), 25, 255, true) * (255 - diff) + 128) / 256); delay = max((int16)distance / 1024, 1); Unit_UpdateMap(2, u); if (delay != 0) { script->delay = delay; script->script--; } return 0; }
/** * Stop the Unit. * * Stack: *none*. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_Stop(ScriptEngine *script) { Unit *u; VARIABLE_NOT_USED(script); u = g_scriptCurrentUnit; Unit_SetSpeed(u, 0); Unit_UpdateMap(2, u); return 0; }
/** * Set the speed of a Unit. * * Stack: 1 - The new speed of the Unit. * * @param script The script engine to operate on. * @return The new speed; it might differ from the value given. */ uint16 Script_Unit_SetSpeed(ScriptEngine *script) { Unit *u; uint16 speed; u = g_scriptCurrentUnit; speed = clamp(STACK_PEEK(1), 0, 255); if (!u->o.flags.s.byScenario) speed = speed * 192 / 256; Unit_SetSpeed(u, speed); return u->speed; }
/** * Set the speed of a Unit. * * Stack: 1 - The new speed of the Unit. * * @param script The script engine to operate on. * @return The new speed; it might differ from the value given. */ uint16 Script_Unit_SetSpeed(ScriptEngine *script) { Unit *u; uint16 speed; u = g_scriptCurrentUnit; speed = STACK_PEEK(1); /* Scenario-based units move on a different speed */ if (!u->o.flags.s.byScenario) speed = speed * 192 / 256; Unit_SetSpeed(u, speed); return u->speed; }
/** * Set the speed of a Unit. * * Stack: 1 - The new speed of the Unit. * * @param script The script engine to operate on. * @return The new speed; it might differ from the value given. */ uint16 Script_Unit_SetSpeed(ScriptEngine *script) { Unit *u; uint16 speed; u = g_scriptCurrentUnit; speed = clamp(STACK_PEEK(1), 0, 255); if (!u->o.flags.s.byScenario) speed = speed * 192 / 256; if (g_table_unitInfo[u->o.type].movementType == MOVEMENT_WINGER) speed = Tools_AdjustToGameSpeed(speed, 0, 255, true); Unit_SetSpeed(u, speed); return u->speed; }
static void Scenario_Load_Unit(const char *key, char *settings) { uint8 houseType, unitType, actionType; int8 orientation; uint16 hitpoints; tile32 position; Unit *u; char *split; VARIABLE_NOT_USED(key); /* The value should have 6 values separated by a ',' */ split = strchr(settings, ','); if (split == NULL) return; *split = '\0'; /* First value is the House type */ houseType = House_StringToType(settings); if (houseType == HOUSE_INVALID) return; /* Find the next value in the ',' separated list */ settings = split + 1; split = strchr(settings, ','); if (split == NULL) return; *split = '\0'; /* Second value is the Unit type */ unitType = Unit_StringToType(settings); if (unitType == UNIT_INVALID) return; /* Find the next value in the ',' separated list */ settings = split + 1; split = strchr(settings, ','); if (split == NULL) return; *split = '\0'; /* Third value is the Hitpoints in percent (in base 256) */ hitpoints = atoi(settings); /* Find the next value in the ',' separated list */ settings = split + 1; split = strchr(settings, ','); if (split == NULL) return; *split = '\0'; /* Fourth value is the position on the map */ position = Tile_UnpackTile(atoi(settings)); /* Find the next value in the ',' separated list */ settings = split + 1; split = strchr(settings, ','); if (split == NULL) return; *split = '\0'; /* Fifth value is orientation */ orientation = (int8)((uint8)atoi(settings)); /* Sixth value is the current state of the unit */ settings = split + 1; actionType = Unit_ActionStringToType(settings); if (actionType == ACTION_INVALID) return; u = Unit_Allocate(UNIT_INDEX_INVALID, unitType, houseType); if (u == NULL) return; u->o.flags.s.byScenario = true; u->o.hitpoints = hitpoints * g_table_unitInfo[unitType].o.hitpoints / 256; u->o.position = position; u->orientation[0].current = orientation; u->actionID = actionType; u->nextActionID = ACTION_INVALID; /* In case the above function failed and we are passed campaign 2, don't add the unit */ if (!Map_IsValidPosition(Tile_PackTile(u->o.position)) && g_campaignID > 2) { Unit_Free(u); return; } /* XXX -- There is no way this is ever possible, as the beingBuilt flag is unset by Unit_Allocate() */ if (!u->o.flags.s.isNotOnMap) Unit_SetAction(u, u->actionID); u->o.seenByHouses = 0x00; Unit_HouseUnitCount_Add(u, u->o.houseID); Unit_SetOrientation(u, u->orientation[0].current, true, 0); Unit_SetOrientation(u, u->orientation[0].current, true, 1); Unit_SetSpeed(u, 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; }