Added transporter patch from Jarod

This commit is contained in:
jsalmon3 2004-07-04 18:35:45 +00:00
parent fd070ea619
commit 8408e1c47c
17 changed files with 133 additions and 50 deletions

View file

@ -92,7 +92,7 @@ static int WaitForTransporter(Unit* unit)
trans = unit->Orders[0].Goal;
if (!trans || !trans->Type->Transporter) {
if (!trans || !CanTransport(trans, unit)) {
// FIXME: destination destroyed??
return 0;
}

View file

@ -6,7 +6,7 @@
// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
// Stratagus - A free fantasy real time strategy game engine
//
/**@name action_build.c - The build building action. */
//

View file

@ -116,7 +116,7 @@ static int ActionMoveGeneric(Unit* unit, const Animation* anim)
// Transporter (un)docking?
//
// FIXME: This is an ugly hack
if (unit->Type->Transporter &&
if (unit->Type->CanTransport &&
((WaterOnMap(unit->X, unit->Y) &&
CoastOnMap(unit->X + xd, unit->Y + yd)) ||
(CoastOnMap(unit->X, unit->Y) &&

View file

@ -67,7 +67,7 @@ void ActionStillGeneric(Unit* unit, int ground)
// If unit is not bunkered and removed, wait
//
if (unit->Removed && (!unit->Container ||
!unit->Container->Type->Transporter ||
!unit->Container->Type->CanTransport ||
!unit->Container->Type->AttackFromTransporter ||
unit->Type->Missile.Missile->Class == MissileClassNone)) {
// If peon is in building or unit is in transporter it is removed.

View file

@ -1489,7 +1489,7 @@ static int FindTransporterOnZone(int waterzone, ZoneSet* destzones,
if (UnitUnusable(unit)) {
continue;
}
if ((unsigned)unit->Type->UnitType != unitType || !unit->Type->Transporter) {
if ((unsigned)unit->Type->UnitType != unitType || !unit->Type->CanTransport) {
continue;
}

View file

@ -503,6 +503,8 @@ int AiFindWall(AiForce* force)
**
** @todo Perfect planning.
** Only works for water transporter!
** @fixme transporter are more selective now (flag with unittypeland).
** We must manage it.
*/
int AiPlanAttack(AiForce* force)
{
@ -526,7 +528,7 @@ int AiPlanAttack(AiForce* force)
aiunit = force->Units;
state = 1;
while (aiunit) {
if (aiunit->Unit->Type->Transporter) {
if (aiunit->Unit->Type->CanTransport) {
DebugPrint("Transporter #%d\n" _C_ UnitNumber(aiunit->Unit));
AiMarkWaterTransporter(aiunit->Unit, watermatrix);
state = 0;
@ -543,7 +545,7 @@ int AiPlanAttack(AiForce* force)
Unit* unit;
unit = AiPlayer->Player->Units[i];
if (unit->Type->Transporter && UnitIdle(unit)) {
if (unit->Type->CanTransport && UnitIdle(unit)) {
DebugPrint("Assign any transporter\n");
AiMarkWaterTransporter(unit, watermatrix);
// FIXME: can be the wrong transporter.

View file

@ -874,10 +874,13 @@ extern int ViewPointDistanceToUnit(const Unit* dest);
((player)->Allied & (1 << (dest)->Player->Player))
/// Return true, if unit is shared vision with the player
#define IsSharedVision(player, dest) \
(( (player)->SharedVision & (1 << (dest)->Player->Player) ) && \
( (dest)->Player->SharedVision & (1 << (player)->Player)))
(((player)->SharedVision & (1 << (dest)->Player->Player)) && \
((dest)->Player->SharedVision & (1 << (player)->Player)))
/// Can this unit-type attack the other (destination)
extern int CanTarget(const UnitType* type,const UnitType* dest);
/// Can transporter transport the other unit
extern int CanTransport(const Unit* transporter,const Unit* unit);
/// Generate a unit reference, a printable unique string for unit
extern char* UnitReference(const Unit*);

View file

@ -5,13 +5,13 @@
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
/**@name unitsound.h - The unit sounds headerfile. */
//
// (c) Copyright 1999,2001-2003 by Lutz Sammer, Fabrice Rossi,
// and Jimmy Salmon
// (c) Copyright 1999-2004 by Lutz Sammer, Fabrice Rossi,
// and Jimmy Salmon
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// $Id$
// $Id$
#ifndef __UNITSOUND_H__
#define __UNITSOUND_H__

View file

@ -698,6 +698,7 @@ struct _unit_type_ {
int AutoBuildRate; ///< The rate at which the building builds itself
int RandomMovementProbability; ///< Probability to move randomly.
int ClicksToExplode; ///< Number of consecutive clicks until unit suicides.
char* CanTransport; ///< Can transport units with this flag.
int MaxOnBoard; ///< Number of Transporter slots.
int StartingResources; ///< Amount of Resources on build
/// @note original only visual effect, we do more with this!
@ -733,7 +734,6 @@ struct _unit_type_ {
unsigned PermanentCloak : 1; ///< Is only visible by CloakDetectors.
unsigned DetectCloak : 1; ///< Can see Cloaked units.
unsigned Coward : 1; ///< Unit will only attack if instructed.
unsigned Transporter : 1; ///< Can transport units
unsigned AttackFromTransporter : 1; ///< Can attack from transporter
unsigned Vanishes : 1; ///< Corpes & destroyed places.
unsigned GroundAttack : 1; ///< Can do command ground attack.

View file

@ -652,7 +652,7 @@ void UpdateButtonPanel(void)
UpgradeIdentAllowed(player, buttonaction->ValueStr) == 'R';
break;
case ButtonUnload:
allow = (Selected[0]->Type->Transporter && Selected[0]->BoardCount);
allow = (Selected[0]->Type->CanTransport && Selected[0]->BoardCount);
break;
case ButtonCancel:
allow = 1;

View file

@ -347,7 +347,7 @@ static void DrawUnitInfo(const Unit* unit)
//
// Draw unit kills and experience.
//
if (stats->Level && !(type->Transporter && unit->BoardCount)) {
if (stats->Level && !(type->CanTransport && unit->BoardCount)) {
sprintf(buf, "XP:~<%d~> Kills:~<%d~>", unit->XP, unit->Kills);
VideoDrawTextCentered(x + 114, y + 8 + 15 + 33, GameFont, buf);
}
@ -462,7 +462,7 @@ static void DrawUnitInfo(const Unit* unit)
//
// Transporting units.
//
if (type->Transporter && unit->BoardCount) {
if (type->CanTransport && unit->BoardCount) {
int j;
if (TheUI.TransportingText) {

View file

@ -145,18 +145,21 @@ void DoRightButton(int sx, int sy)
dest = NULL;
}
// Don't allow stopping enemy transporters!
if (dest && dest->Type->Transporter && !dest->Type->Building &&
PlayersTeamed(ThisPlayer->Player, dest->Player->Player)) {
// n0b0dy: So we are clicking on a transporter. We have to:
// 1) Flush the transporters orders.
// 2) Tell the transporter to follow the units. We have to queue all
// these follow orders, so the transport will go and pick the up
// 3) Tell all selected land units to go board the transporter.
//
// Here we flush the order queue
SendCommandStopUnit(dest);
desttransporter = dest;
if (dest && dest->Type->CanTransport) {
for (i = 0; i < NumSelected; i++) {
if (CanTransport(dest, Selected[i])) {
// We are clicking on a transporter. We have to:
// 1) Flush the transporters orders.
// 2) Tell the transporter to follow the units. We have to queue all
// these follow orders, so the transport will go and pick them up
// 3) Tell all selected land units to go board the transporter.
// Here we flush the order queue
SendCommandStopUnit(dest);
desttransporter = dest;
break;
}
}
}
// FIXME: the next should be rewritten, must select the units with
@ -190,8 +193,7 @@ void DoRightButton(int sx, int sy)
//
// Enter transporters?
//
if (dest && dest->Type->Transporter && dest->Player == unit->Player &&
unit->Type->UnitType == UnitTypeLand) {
if (dest && CanTransport(dest, unit)) {
dest->Blink = 4;
DebugPrint("Board transporter\n");
// Let the transporter move to the unit. And QUEUE!!!
@ -427,7 +429,7 @@ static void HandleMouseOn(int x, int y)
}
}
}
if (NumSelected == 1 && Selected[0]->Type->Transporter && Selected[0]->BoardCount &&
if (NumSelected == 1 && Selected[0]->Type->CanTransport && Selected[0]->BoardCount &&
!BigMapMode) {
for (i = Selected[0]->BoardCount - 1; i >= 0; --i) {
if (x >= TheUI.TransportingButtons[i].X &&
@ -868,13 +870,18 @@ static int SendMove(int sx, int sy)
int ret;
ret = 0;
// Move to a transporter.
if ((transporter = UnitUnderCursor) &&
transporter->Type->Transporter &&
(transporter->Player == ThisPlayer ||
PlayersTeamed(ThisPlayer->Player, transporter->Player->Player))) {
SendCommandStopUnit(transporter);
ret = 1;
// Move to a transporter.
if ((transporter = UnitUnderCursor) && transporter->Type->CanTransport) {
for (i = 0; i < NumSelected; ++i) {
if (CanTransport(transporter, Selected[i])) {
SendCommandStopUnit(transporter);
ret = 1;
break;
}
}
if (i == NumSelected) {
transporter = NULL;
}
} else {
transporter = NULL;
}
@ -883,7 +890,7 @@ static int SendMove(int sx, int sy)
for (i = 0; i < NumSelected; ++i) {
unit = Selected[i];
if (transporter && unit->Type->UnitType == UnitTypeLand) {
if (transporter && CanTransport(transporter, unit)) {
transporter->Blink = 4;
SendCommandFollow(transporter, unit, 0);
SendCommandBoard(unit, -1, -1, transporter, flush);

View file

@ -497,8 +497,42 @@ static int CclDefineUnitType(lua_State* l)
type->PermanentCloak = LuaToBoolean(l, -1);
} else if (!strcmp(value, "DetectCloak")) {
type->DetectCloak = LuaToBoolean(l, -1);
} else if (!strcmp(value, "Transporter")) {
type->Transporter = LuaToBoolean(l, -1);
} else if (!strcmp(value, "CanTransport")) {
//
// Warning: CanTransport should only be used AFTER all bool flags
// have been defined.
//
if (!lua_istable(l, -1)) {
lua_pushstring(l, "incorrect argument");
lua_error(l);
}
if (type->MaxOnBoard == 0) { // set default value.
type->MaxOnBoard = 1;
}
if (!type->CanTransport) {
type->CanTransport = calloc(NumberBoolFlag, sizeof(*type->CanTransport));
}
// FIXME : add flag for kill/unload units inside.
subargs = luaL_getn(l, -1);
for (k = 0; k < subargs; ++k) {
lua_rawgeti(l, -1, k + 1);
value = LuaToString(l, -1);
lua_pop(l, 1);
++k;
for (i = 0; i < NumberBoolFlag; ++i) {
if (!strcmp(value, BoolFlagName[i])) {
lua_rawgeti(l, -1, k + 1);
value = LuaToString(l, -1);
lua_pop(l, 1);
type->CanTransport[i] = Ccl2Condition(l, value);
break;
}
}
if (i != NumberBoolFlag) {
continue;
}
LuaError(l, "Unsupported flag tag for CanTransport: %s" _C_ value);
}
} else if (!strcmp(value, "AttackFromTransporter")) {
type->AttackFromTransporter = LuaToBoolean(l, -1);
} else if (!strcmp(value, "Coward")) {
@ -682,7 +716,6 @@ static int CclDefineUnitType(lua_State* l)
if (i != NumberBoolFlag) {
continue;
}
printf("\n%s\n", type->Name);
LuaError(l, "Unsupported flag tag for can-target-flag: %s" _C_ value);
}
} else if (!strcmp(value, "SelectableByRectangle")) {

View file

@ -2625,7 +2625,8 @@ void LetUnitDie(Unit* unit)
}
// Transporters lose their units
if (unit->Type->Transporter) {
if (unit->Type->CanTransport) {
// FIXME: destroy or unload : do a flag.
DestroyAllInside(unit);
}
@ -2664,6 +2665,7 @@ void DestroyAllInside(Unit* source)
// No Corpses, we are inside something, and we can't be seen
unit = source->UnitInside;
for (i = source->InsideCount; i; --i, unit = unit->NextContained) {
// Transporter inside a transporter?
if (unit->UnitInside) {
DestroyAllInside(unit);
}
@ -3084,6 +3086,40 @@ int CanTarget(const UnitType* source, const UnitType* dest)
return 0;
}
/**
** Can the transporter transport the other unit.
**
** @param transporter Unit which is the transporter.
** @param unit Unit which wants to go in the transporter.
**
** @return 1 if transporter can transport unit, 0 else.
*/
int CanTransport(const Unit* transporter, const Unit* unit)
{
int i;
if (!transporter->Type->CanTransport || unit->Type->Building) {
return 0;
}
if (transporter->BoardCount >= transporter->Type->MaxOnBoard) { // full
return 0;
}
// FIXME: remove UnitTypeLand requirement
if (PlayersTeamed(transporter->Player->Player, unit->Player->Player) &&
unit->Type->UnitType != UnitTypeLand) {
return 0;
}
for (i = 0; i < NumberBoolFlag; i++) {
if (transporter->Type->CanTransport[i] != CONDITION_TRUE) {
if ((transporter->Type->CanTransport[i] == CONDITION_ONLY) ^
unit->Type->BoolFlag[i]) {
return 0;
}
}
}
return 1;
}
/*----------------------------------------------------------------------------
-- SAVE/LOAD
----------------------------------------------------------------------------*/

View file

@ -983,7 +983,7 @@ static void DrawDecoration(const Unit* unit, const UnitType* type, int x, int y)
//
// Transporter with units on board.
//
} else if (unit->Type->Transporter) {
} else if (unit->Type->CanTransport) {
DrawManaBar(x, y, type, unit->Type->MaxOnBoard, unit->BoardCount);
}
}
@ -1051,7 +1051,7 @@ static void DrawDecoration(const Unit* unit, const UnitType* type, int x, int y)
//
// Transporter with units on board.
//
} else if (unit->Type->Transporter) {
} else if (unit->Type->CanTransport) {
DrawManaSprite(x, y, type, unit->Type->MaxOnBoard, unit->BoardCount);
}
}

View file

@ -317,7 +317,7 @@ Unit* TransporterOnMapTile(int tx, int ty)
n = UnitCacheOnTile(tx, ty, table);
for (i = 0; i < n; ++i) {
if (table[i]->Type->Transporter) {
if (table[i]->Type->CanTransport) {
return table[i];
}
}

View file

@ -203,7 +203,7 @@ void UpdateStats(int reset)
MapFieldAirUnit; // already occuppied
break;
case UnitTypeNaval: // on water
if (type->Transporter) {
if (type->CanTransport) {
type->MovementMask =
MapFieldLandUnit |
MapFieldSeaUnit |
@ -481,7 +481,8 @@ void ParsePudUDTA(const char* udta, int length __attribute__((unused)))
unittype->ResInfo[OilCost]->WaitAtDepot = 150;
unittype->ResInfo[OilCost]->ResourceCapacity = 100;
}
unittype->Transporter = BIT(10, v);
unittype->CanTransport = BIT(10, v) ?
calloc(NumberBoolFlag, sizeof(*unittype->CanTransport)) : NULL;
unittype->CanStore[GoldCost] = BIT(12, v);
unittype->Vanishes = BIT(13, v);
unittype->GroundAttack = BIT(14, v);
@ -931,6 +932,7 @@ void CleanUnitTypes(void)
free(type->BoolFlag);
free(type->CanTargetFlag);
free(type->CanTransport);
if (type->SameSprite) {
free(type->SameSprite);