/** * Check if the given tile is a valid destination. In case of for example * a carry-all it checks if the unit carrying can be placed on destination. * In case of structures, it checks if you can walk into it. * * Stack: 1 - An encoded tile, indicating the destination. * * @param script The script engine to operate on. * @return ??. */ uint16 Script_Unit_IsValidDestination(ScriptEngine *script) { Unit *u; Unit *u2; uint16 encoded; uint16 index; u = g_scriptCurrentUnit; encoded = STACK_PEEK(1); index = Tools_Index_Decode(encoded); switch (Tools_Index_GetType(encoded)) { case IT_TILE: if (!Map_IsValidPosition(index)) return 1; if (u->o.linkedID == 0xFF) return 1; u2 = Unit_Get_ByIndex(u->o.linkedID); u2->o.position = Tools_Index_GetTile(encoded); if (!Unit_IsTileOccupied(u2)) return 0; u2->o.position.tile = 0xFFFFFFFF; return 1; case IT_STRUCTURE: { Structure *s; s = Structure_Get_ByIndex(index); if (s->o.houseID == Unit_GetHouseID(u)) return 0; if (u->o.linkedID == 0xFF) return 1; u2 = Unit_Get_ByIndex(u->o.linkedID); return Unit_IsValidMovementIntoStructure(u2, s) != 0 ? 1 : 0; } default: return 1; } }
/** * 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; }
/** * Set a new target, and rotate towards him if needed. * * Stack: 1 - An encoded tile of the unit/tile to target. * * @param script The script engine to operate on. * @return The new target. */ uint16 Script_Unit_SetTarget(ScriptEngine *script) { Unit *u; uint16 target; tile32 tile; int8 orientation; u = g_scriptCurrentUnit; target = STACK_PEEK(1); if (target == 0 || !Tools_Index_IsValid(target)) { u->targetAttack = 0; return 0; } tile = Tools_Index_GetTile(target); orientation = Tile_GetDirection(u->o.position, tile); u->targetAttack = target; if (!g_table_unitInfo[u->o.type].o.flags.hasTurret) { u->targetMove = target; Unit_SetOrientation(u, orientation, false, 0); } Unit_SetOrientation(u, orientation, false, 1); return u->targetAttack; }
/** * Finds a structure. * * Stack: 1 - A structure type. * * @param script The script engine to operate on. * @return An encoded structure index, or 0 if none found. */ uint16 Script_Unit_FindStructure(ScriptEngine *script) { Unit *u; PoolFindStruct find; u = g_scriptCurrentUnit; find.houseID = Unit_GetHouseID(u); find.index = 0xFFFF; find.type = STACK_PEEK(1); while (true) { Structure *s; s = Structure_Find(&find); if (s == NULL) break; if (s->state != STRUCTURE_STATE_IDLE) continue; if (s->o.linkedID != 0xFF) continue; if (s->o.script.variables[4] != 0) continue; return Tools_Index_Encode(s->o.index, IT_STRUCTURE); } return 0; }
/** * Get information about the unit, like hitpoints, current target, etc. * * Stack: 1 - Which information you would like. * * @param script The script engine to operate on. * @return The information you requested. */ uint16 Script_Unit_GetInfo(ScriptEngine *script) { const UnitInfo *ui; Unit *u; u = g_scriptCurrentUnit; ui = &g_table_unitInfo[u->o.type]; switch (STACK_PEEK(1)) { case 0x00: return u->o.hitpoints * 256 / ui->o.hitpoints; case 0x01: return Tools_Index_IsValid(u->targetMove) ? u->targetMove : 0; case 0x02: return ui->fireDistance << 8; case 0x03: return u->o.index; case 0x04: return u->orientation[0].current; case 0x05: return u->targetAttack; case 0x06: if (u->originEncoded == 0 || u->o.type == UNIT_HARVESTER) Unit_FindClosestRefinery(u); return u->originEncoded; case 0x07: return u->o.type; case 0x08: return Tools_Index_Encode(u->o.index, IT_UNIT); case 0x09: return u->movingSpeed; case 0x0A: return abs(u->orientation[0].target - u->orientation[0].current); case 0x0B: return u->currentDestination.tile == 0 ? 0 : 1; case 0x0C: return u->fireDelay == 0 ? 1 : 0; case 0x0D: return ui->flags.explodeOnDeath; case 0x0E: return Unit_GetHouseID(u); case 0x0F: return u->o.flags.s.byScenario ? 1 : 0; case 0x10: return u->orientation[ui->o.flags.hasTurret ? 1 : 0].current; case 0x11: return abs(u->orientation[ui->o.flags.hasTurret ? 1 : 0].target - u->orientation[ui->o.flags.hasTurret ? 1 : 0].current); case 0x12: return (ui->movementType & 0x40) == 0 ? 0 : 1; case 0x13: return (u->o.seenByHouses & (1 << g_playerHouseID)) == 0 ? 0 : 1; default: return 0; } }
/** * Draws a string. * * Stack: 1 - The index of the string to draw. * 2-4 - The arguments for the string. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Team_DisplayText(ScriptEngine *script) { Team *t; char *text; uint16 offset; t = g_scriptCurrentTeam; if (t->houseID == g_playerHouseID) return 0; offset = BETOH16(*(script->scriptInfo->text + STACK_PEEK(1))); text = (char *)script->scriptInfo->text + offset; GUI_DisplayText(text, 0, STACK_PEEK(2), STACK_PEEK(3), STACK_PEEK(4)); return 0; }
/** * Find a UnitType and make it go to the current structure. In general, type * should be a Carry-All for this to make any sense. * * Stack: 1 - An unit type. * * @param script The script engine to operate on. * @return unknown. */ uint16 Script_Structure_FindUnitByType(ScriptEngine *script) { Structure *s; Unit *u; Unit *carryall; uint16 type; uint16 position; uint16 carryallIndex; s = g_scriptCurrentStructure; if (s->state != STRUCTURE_STATE_READY) return IT_NONE; if (s->o.linkedID == 0xFF) return IT_NONE; type = STACK_PEEK(1); position = Structure_FindFreePosition(s, false); u = Unit_Get_ByIndex(s->o.linkedID); if (g_playerHouseID == s->o.houseID && u->o.type == UNIT_HARVESTER && u->targetLast.tile == 0 && position != 0) { return IT_NONE; } carryall = Unit_CallUnitByType(type, s->o.houseID, Tools_Index_Encode(s->o.index, IT_STRUCTURE), position == 0); if (carryall == NULL) return IT_NONE; carryallIndex = Tools_Index_Encode(carryall->o.index, IT_UNIT); Object_Script_Variable4_Set(&s->o, carryallIndex); return carryallIndex; }
int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts) { XMLCONFPARSER *xcp = (XMLCONFPARSER*)UserData; LPXMLRUNTIMEATT att; int *pstate = STACK_PEEK(xcp->stateStack); xcp->state = (pstate) ? *pstate : NONE; if (xcp->inMixedContent || xcp->state == TEST) { /* + other tags that allow mixed content tested here */ /* if we're in mixed content, we don't bother to use stack, just incrementing (and decrementing in EndElement) the counter: */ xcp->inMixedContent++; /* could call mixed content legal tag check routine here e.g. if (!isvalidmixedcontent(state, qName)) return sin(); */ fprintf(PFOUT, "<%s>", qName); return 0; } if (xcp->state == NONE && !strcmp(qName, "TESTSUITE")) { if (att = XMLParser_GetNamedItem(xcp->parser, "PROFILE")) fprintf(PFOUT, "<h1><b>%s</b></h1><br><h3>Parsifal XML Parser %s</h3>", att->value, XMLParser_GetVersionString()); xcp->state = TESTSUITE; } else if (xcp->state == TESTSUITE && !strcmp(qName, "TESTCASES")) { if (att = XMLParser_GetNamedItem(xcp->parser, "PROFILE")) { /* new testcase, spit out the profile header: */ fprintf(PFOUT, "<br><br><h2>Testcase profile: <b>%s</b></h2><br>", att->value); fputs("<table cellspacing='0'>", PFOUT); /* open table for results */ } xcp->state = TESTCASES; } else if (xcp->state == TESTCASES) { if (!strcmp(qName, "TEST")) { if (att = XMLParser_GetNamedItem(xcp->parser, "URI")) { /* new test, run it: */ if (!RunTest(xcp, att->value)) fprintf(PFERR, "Fatal Error running test: %s\n", att->value); } xcp->state = TEST; } else if (!strcmp(qName, "TESTCASES")) { /* for some reason there's TESTCASES inside TESTCASES in ibm tests, so it must ust be handled here: */ xcp->state = TESTCASES; } } else { fprintf(PFERR, "Unexpected tag: %s\n", qName); return XML_ABORT; } STACK_PUSH(xcp->stateStack, &xcp->state); return 0; }
/** * Gets the best target for the current unit. * * Stack: 1 - How to determine the best target. * * @param script The script engine to operate on. * @return The encoded index of the best target or 0 if none found. */ uint16 Script_Unit_FindBestTarget(ScriptEngine *script) { Unit *u; u = g_scriptCurrentUnit; return Unit_FindBestTargetEncoded(u, STACK_PEEK(1)); }
/** * Calculate the route to a tile. * * Stack: 1 - An encoded tile to calculate the route to. * * @param script The script engine to operate on. * @return 0 if we arrived on location, 1 otherwise. */ uint16 Script_Unit_CalculateRoute(ScriptEngine *script) { Unit *u; uint16 encoded; uint16 packedSrc; uint16 packedDst; u = g_scriptCurrentUnit; encoded = STACK_PEEK(1); if (u->currentDestination.tile != 0 || !Tools_Index_IsValid(encoded)) return 1; packedSrc = Tile_PackTile(u->o.position); packedDst = Tools_Index_GetPackedTile(encoded); if (packedDst == packedSrc) { u->route[0] = 0xFF; u->targetMove = 0; return 0; } if (u->route[0] == 0xFF) { Pathfinder_Data res; uint8 buffer[42]; res = Script_Unit_Pathfinder(packedSrc, packedDst, buffer, 40); memcpy(u->route, res.buffer, min(res.routeSize, 14)); if (u->route[0] == 0xFF) { u->targetMove = 0; if (u->o.type == UNIT_SANDWORM) { script->delay = 720; } } } else { uint16 distance; distance = Tile_GetDistancePacked(packedDst, packedSrc); if (distance < 14) u->route[distance] = 0xFF; } if (u->route[0] == 0xFF) return 1; if (u->orientation[0].current != (int8)(u->route[0] * 32)) { Unit_SetOrientation(u, (int8)(u->route[0] * 32), false, 0); return 1; } if (!Unit_StartMovement(u)) { u->route[0] = 0xFF; return 0; } memmove(&u->route[0], &u->route[1], 13); u->route[13] = 0xFF; return 1; }
/** * Make an explosion at the coordinates of the unit. * It does damage to the surrounding units based on the unit. * * Stack: 1 - Explosion type * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_ExplosionSingle(ScriptEngine *script) { Unit *u; u = g_scriptCurrentUnit; Map_MakeExplosion(STACK_PEEK(1), u->o.position, g_table_unitInfo[u->o.type].o.hitpoints, Tools_Index_Encode(u->o.index, IT_UNIT)); return 0; }
/** * Set the orientation of a unit. * * Stack: 1 - New orientation for unit. * * @param script The script engine to operate on. * @return The current orientation of the unit (it will move to the requested over time). */ uint16 Script_Unit_SetOrientation(ScriptEngine *script) { Unit *u; u = g_scriptCurrentUnit; Unit_SetOrientation(u, (int8)STACK_PEEK(1), false, 0); return u->orientation[0].current; }
/** * Rotate the turret to look at a tile. * * Stack: 1 - Tile to look at. * * @param script The script engine to operate on. * @return 0 if looking at target, otherwise 1. */ uint16 Script_Structure_RotateTurret(ScriptEngine *script) { Structure *s; tile32 lookAt; Tile *tile; uint16 baseSpriteID; uint16 encoded; int16 rotation; int16 rotationNeeded; int16 rotateDiff; encoded = STACK_PEEK(1); if (encoded == 0) return 0; s = g_scriptCurrentStructure; lookAt = Tools_Index_GetTile(encoded); tile = &g_map[Tile_PackTile(s->o.position)]; /* Find the base sprite of the structure */ if (s->o.type == STRUCTURE_ROCKET_TURRET) { baseSpriteID = g_iconMap[g_iconMap[ICM_ICONGROUP_BASE_ROCKET_TURRET] + 2]; } else { baseSpriteID = g_iconMap[g_iconMap[ICM_ICONGROUP_BASE_DEFENSE_TURRET] + 2]; } rotation = tile->groundSpriteID - baseSpriteID; if (rotation < 0 || rotation > 7) return 1; /* Find what rotation we should have to look at the target */ rotationNeeded = Orientation_Orientation256ToOrientation8(Tile_GetDirection(s->o.position, lookAt)); /* Do we need to rotate */ if (rotationNeeded == rotation) return 0; /* Find the fastest way to rotate to the correct rotation */ rotateDiff = rotationNeeded - rotation; if (rotateDiff < 0) rotateDiff += 8; if (rotateDiff < 4) { rotation++; } else { rotation--; } rotation &= 0x7; /* Set the new sprites */ tile->groundSpriteID = baseSpriteID + rotation; s->rotationSpriteDiff = rotation; Map_Update(Tile_PackTile(s->o.position), 0, false); return 1; }
int XMLAPI DTDValidate_Characters(void *UserData, const XMLCH *chars, int cbSize) { LPXMLDTDVALIDATOR v = (LPXMLDTDVALIDATOR)UserData; struct vContext *c = STACK_PEEK(v->ContextStack); if (c && !(c->e->type == XMLCTYPE_MIXED || c->e->type == XMLCTYPE_ANY)) { Er_(v, NULL, ERR_XMLDTDV_PCDATA_NOT_ALLOWED, c->e->name); MAYRET(XML_ABORT); } return (v->charactersHandler) ? v->charactersHandler(v, chars, cbSize) : 0; }
int XMLAPI DTDValidate_IgnorableWhitespace(void *UserData, const XMLCH *chars, int cbSize) { LPXMLDTDVALIDATOR v = (LPXMLDTDVALIDATOR)UserData; struct vContext *c = STACK_PEEK(v->ContextStack); if (c && (c->e->type == XMLCTYPE_MIXED || c->e->type == XMLCTYPE_ANY)) { return (v->charactersHandler) ? v->charactersHandler(v, chars, cbSize) : 0; } return (v->ignorableWhitespaceHandler) ? v->ignorableWhitespaceHandler(v, chars, cbSize) : 0; }
/** * Play a voice on the structure. * * Stack: 1 - The VoiceID to play. * * @param script The script engine to operate on. * @return unknown. */ uint16 Script_Structure_VoicePlay(ScriptEngine *script) { Structure *s; s = g_scriptCurrentStructure; if (s->o.houseID != g_playerHouseID) return 0; Voice_PlayAtTile(STACK_PEEK(1), s->o.position); return 0; }
/** * Change the sprite (offset) of the unit. * * Stack: 1 - The new sprite offset. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_SetSprite(ScriptEngine *script) { Unit *u; u = g_scriptCurrentUnit; u->spriteOffset = -(STACK_PEEK(1) & 0xFF); Unit_UpdateMap(2, u); return 0; }
/** * Get a random tile around the Unit. * * Stack: 1 - An encoded index of a tile, completely ignored, as long as it is a tile. * * @param script The script engine to operate on. * @return An encoded tile, or 0. */ uint16 Script_Unit_GetRandomTile(ScriptEngine *script) { Unit *u; tile32 tile; u = g_scriptCurrentUnit; if (Tools_Index_GetType(STACK_PEEK(1)) != IT_TILE) return 0; tile = Tile_MoveByRandom(u->o.position, 80, true); return Tools_Index_Encode(Tile_PackTile(tile), IT_TILE); }
/** * Unknown function 0543. * * Stack: 1 - A distance. * * @param script The script engine to operate on. * @return The number of moving units. */ uint16 Script_Team_Unknown0543(ScriptEngine *script) { Team *t; uint16 count = 0; uint16 distance; PoolFindStruct find; t = g_scriptCurrentTeam; distance = STACK_PEEK(1); find.houseID = t->houseID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { Unit *u; tile32 tile; uint16 distanceUnitDest; uint16 distanceUnitTeam; uint16 distanceTeamDest; u = Unit_Find(&find); if (u == NULL) break; if (t->index != u->team - 1) continue; tile = Tools_Index_GetTile(u->targetMove); distanceUnitTeam = Tile_GetDistanceRoundedUp(u->o.position, t->position); if (u->targetMove != 0) { distanceUnitDest = Tile_GetDistanceRoundedUp(u->o.position, tile); distanceTeamDest = Tile_GetDistanceRoundedUp(t->position, tile); } else { distanceUnitDest = 64; distanceTeamDest = 64; } if ((distanceUnitDest < distanceTeamDest && (distance + 2) < distanceUnitTeam) || (distanceUnitDest >= distanceTeamDest && distanceUnitTeam > distance)) { Unit_SetAction(u, ACTION_MOVE); tile = Tile_MoveByRandom(t->position, distance << 4, true); Unit_SetDestination(u, Tools_Index_Encode(Tile_PackTile(tile), IT_TILE)); count++; continue; } Unit_SetAction(u, ACTION_GUARD); } return count; }
/** * 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; }
/** * 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; }
int XMLAPI DTDValidate_EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName) { LPXMLDTDVALIDATOR v = (LPXMLDTDVALIDATOR)UserData; struct vContext *c = STACK_PEEK(v->ContextStack); if (c) { if (!(c->ctx->mark & SMARK_FINAL)) { Er_(v, c->ctx, ERR_XMLDTDV_CONTENT_MODEL_CANNOT_END, c->e->name); MAYRET(XML_ABORT); } STACK_REMOVE(v->ContextStack); } return (v->endElementHandler) ? v->endElementHandler(v, uri, localName, qName) : 0; }
int XMLAPI DTDValidate_StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts) { LPXMLDTDVALIDATOR v = (LPXMLDTDVALIDATOR)UserData; struct vContext *c; void *d; if (v->ContextStack->length) { c = STACK_PEEK(v->ContextStack); if (c->e->type != XMLCTYPE_ANY) { struct FSAState *ctx = Validate(c->ctx, (XMLCH*)qName); if (!ctx) { Er_(v, c->ctx, ERR_XMLDTDV_ELEMENT_NOT_ALLOWED, c->e->name, qName); MAYRET(XML_ABORT); } else c->ctx = ctx; } } else if (v->startElementHandlerFilter == DTDValidate_StartElement && v->parser->prt->doctypeStr) { /* test for ERR_XMLDTDV_ROOTELEMENT_MISMATCH */ if (strcmp(qName, v->parser->prt->doctypeStr)) { Er_(v, NULL, ERR_XMLDTDV_ROOTELEMENT_MISMATCH, v->parser->prt->doctypeStr); MAYRET(XML_ABORT); } } if (!(c = STACK_PUSH(v->ContextStack, NULL))) { Er_(v, NULL, ERR_XMLDTDV_MEMORY_ALLOC); return XML_ABORT; } d = (v->ElementTable) ? XMLHTable_Lookup(v->ElementTable, (char*)qName) : NULL; /* catches the case of missing DTD too */ if (!d || d == EMPTYSTR) { /* note that we're also testing the empty string (element is in hashtable because it was used in cp but it wasn't declared) */ Er_(v, NULL, ERR_XMLDTDV_UNDECLARED_ELEMENT, qName); MAYRET(XML_ABORT); c->e = (struct ElementDecl*)&AnyElement; c->ctx = c->e->startState; return (v->startElementHandler) ? v->startElementHandler(v, uri, localName, qName, atts) : 0; } c->e = d; c->ctx = c->e->startState; if (!ValidateAtts(v, c->e, atts)) return XML_ABORT; return (v->startElementHandler) ? v->startElementHandler(v, uri, localName, qName, atts) : 0; }
/** * Make 8 explosions: 1 at the unit, and 7 around him. * It does damage to the surrounding units with predefined damage, but * anonymous. * * Stack: 1 - The radius of the 7 explosions. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_ExplosionMultiple(ScriptEngine *script) { Unit *u; uint8 i; u = g_scriptCurrentUnit; Map_MakeExplosion(EXPLOSION_DEATH_HAND, u->o.position, Tools_RandomLCG_Range(25, 50), 0); for (i = 0; i < 7; i++) { Map_MakeExplosion(EXPLOSION_DEATH_HAND, Tile_MoveByRandom(u->o.position, STACK_PEEK(1), false), Tools_RandomLCG_Range(75, 150), 0); } return 0; }
/** * Find the direction a tile is, seen from the structure. If the tile is * invalid it gives the direction the structure is currently looking at. * * Stack: 1 - Tile to get the direction to, or the current direction of the * structure in case the tile is invalid. * * @param script The script engine to operate on. * @return The direction (value between 0 and 7, shifted to the left with 5). */ uint16 Script_Structure_GetDirection(ScriptEngine *script) { Structure *s; tile32 tile; uint16 encoded; s = g_scriptCurrentStructure; encoded = STACK_PEEK(1); if (!Tools_Index_IsValid(encoded)) return s->rotationSpriteDiff << 5; tile = Tools_Index_GetTile(encoded); return Orientation_Orientation256ToOrientation8(Tile_GetDirection(s->o.position, tile)) << 5; }
/** * 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; }
/** * Sets the action for the current unit. * * Stack: 1 - The action. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_SetAction(ScriptEngine *script) { Unit *u; ActionType action; u = g_scriptCurrentUnit; action = STACK_PEEK(1); if (u->o.houseID == g_playerHouseID && action == ACTION_HARVEST && u->nextActionID != ACTION_INVALID) return 0; Unit_SetAction(u, action); 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; if (g_table_unitInfo[u->o.type].movementType == MOVEMENT_WINGER) speed = Tools_AdjustToGameSpeed(speed, 0, 255, true); Unit_SetSpeed(u, speed); return u->speed; }
/** * Find a Unit which is within range and not an ally. * * Stack: 1 - Range to find a target in (amount of tiles multiplied with 256). * * @param script The script engine to operate on. * @return The Unit Index of the closest unit within range and not friendly, * or 0 if none exists. */ uint16 Script_Structure_FindTargetUnit(ScriptEngine *script) { PoolFindStruct find; Structure *s; Unit *u; uint32 distanceCurrent; uint32 targetRange; s = g_scriptCurrentStructure; targetRange = STACK_PEEK(1); distanceCurrent = 32000; u = NULL; find.houseID = HOUSE_INVALID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { uint16 distance; Unit *uf; uf = Unit_Find(&find); if (uf == NULL) break; if (House_AreAllied(s->o.houseID, uf->o.houseID)) continue; if (uf->o.type != UNIT_ORNITHOPTER) { if ((uf->o.seenByHouses & (1 << s->o.houseID)) == 0) continue; } distance = Tile_GetDistance(uf->o.position, s->o.position); if (distance >= distanceCurrent) continue; if (uf->o.type == UNIT_ORNITHOPTER) { if (distance >= targetRange * 3) continue; } else { if (distance >= targetRange) continue; } /* ENHANCEMENT -- The original code swapped the assignment, making it do nothing, Now it finds the closest unit to shoot at, what seems to be the intention */ if (g_dune2_enhanced) distanceCurrent = distance; u = uf; } if (u == NULL) return IT_NONE; return Tools_Index_Encode(u->o.index, IT_UNIT); }
/** * Loads a new script for the current team. * * Stack: 1 - The script type. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Team_Load(ScriptEngine *script) { Team *t; uint16 type; t = g_scriptCurrentTeam; type = STACK_PEEK(1); if (t->action == type) return 0; t->action = type; Script_Reset(&t->script, g_scriptTeam); Script_Load(&t->script, type & 0xFF); return 0; }