1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <tank/TankDefinition.h>
22 #include <tank/Tank.h>
23 #include <tank/TankColorGenerator.h>
24 #include <tank/TankModelStore.h>
25 #include <tank/TankAvatar.h>
26 #include <tank/TankState.h>
27 #include <target/TargetLife.h>
28 #include <target/TargetParachute.h>
29 #include <target/TargetShield.h>
30 #include <target/TargetState.h>
31 #include <tankai/TankAIStore.h>
33 #include <tankgraph/TargetRendererImplTank.h>
35 #include <common/RandomGenerator.h>
36 #include <common/OptionsScorched.h>
37 #include <common/Defines.h>
38 #include <weapons/AccessoryStore.h>
39 #include <engine/ScorchedContext.h>
40 #include <server/ScorchedServer.h>
42 TankDefinition::TankDefinition() :
44 life_(100), boundingsphere_(true),
46 driveovertodestroy_(false)
48 shadow_
.setDrawShadow(false);
51 TankDefinition::~TankDefinition()
55 bool TankDefinition::readXML(XMLNode
*node
, const char *base
)
57 node
->getNamedChild("name", name_
, false);
58 node
->getNamedChild("life", life_
, false);
59 node
->getNamedChild("shield", shield_
, false);
60 node
->getNamedChild("parachute", parachute_
, false);
61 node
->getNamedChild("boundingsphere", boundingsphere_
, false);
63 if (!node
->getNamedChild("ai", ai_
)) return false;
64 if (!node
->getNamedChild("model", tankmodel_
)) return false;
65 node
->getNamedChild("team", team_
, false);
67 node
->getNamedChild("driveovertodestroy", driveovertodestroy_
, false);
68 node
->getNamedChild("removeaction", removeaction_
, false);
69 node
->getNamedChild("burnaction", burnaction_
, false);
71 if (!shadow_
.readXML(node
, base
)) return false;
72 if (!groups_
.readXML(node
)) return false;
74 return node
->failChildren();
77 Tank
*TankDefinition::createTank(unsigned int playerId
,
78 FixedVector
&position
,
79 ScorchedContext
&context
,
80 RandomGenerator
&generator
)
82 Vector color
= TankColorGenerator::getTeamColor(team_
);
83 if (team_
== 0) color
= Vector(0.7f
, 0.7f
, 0.7f
);
86 context
.getTankModels().getModelByName(
90 if (!model
|| strcmp("Random", model
->getName()) == 0)
92 S3D::dialogExit("TankDefinition",
93 S3D::formatStringBuffer("Cannot find a tank model named \"%s\"",
97 Tank
*tank
= new Tank(context
, playerId
, 0,
98 name_
, color
, model
->getName(), model
->getTypeName());
99 tank
->getLife().setBoundingSphere(boundingsphere_
);
101 if (context
.getServerMode())
103 TankAI
*ai
= ScorchedServer::instance()->getTankAIs().getAIByName(ai_
.c_str());
106 S3D::dialogExit("TankDefinition",
107 S3D::formatStringBuffer("Cannot find a tank ai named \"%s\"",
111 tank
->setTankAI(ai
->createCopy(tank
));
112 std::string uniqueId
= S3D::formatStringBuffer("Tank - %u", playerId
);
113 tank
->setUniqueId(uniqueId
.c_str());
118 tank
->setRenderer(new TargetRendererImplTank(tank
));
122 if (context
.getOptionsGame().getTeams() > 1)
124 tank
->setTeam(team_
);
126 tank
->getAvatar().loadFromFile(S3D::getDataFile("data/avatars/computer.png"));
127 tank
->getLife().setMaxLife(life_
);
128 tank
->getLife().setSize(size_
);
129 tank
->getTargetState().setDriveOverToDestroy(driveovertodestroy_
);
130 tank
->getState().setState(TankState::sInitializing
);
131 tank
->getState().setState(TankState::sPending
);
135 if (shield_
.c_str()[0] && 0 != strcmp(shield_
.c_str(), "none"))
137 Accessory
*shield
= context
.getAccessoryStore().
138 findByPrimaryAccessoryName(shield_
.c_str());
141 S3D::dialogExit("Scorched3D",
142 S3D::formatStringBuffer("Failed to find shield named \"%s\"",
146 tank
->getShield().setCurrentShield(shield
);
149 if (parachute_
.c_str()[0] && 0 != strcmp(parachute_
.c_str(), "none"))
151 Accessory
*parachute
= context
.getAccessoryStore().
152 findByPrimaryAccessoryName(parachute_
.c_str());
155 S3D::dialogExit("Scorched3D",
156 S3D::formatStringBuffer("Failed to find parachute named \"%s\"",
157 parachute_
.c_str()));
160 tank
->getParachute().setCurrentParachute(parachute
);
163 if (removeaction_
.c_str()[0] && 0 != strcmp(removeaction_
.c_str(), "none"))
165 Accessory
*action
= context
.getAccessoryStore().
166 findByPrimaryAccessoryName(removeaction_
.c_str());
167 if (!action
|| action
->getType() != AccessoryPart::AccessoryWeapon
)
169 S3D::dialogExit("Scorched3D",
170 S3D::formatStringBuffer("Failed to find death action \"%s\"",
171 removeaction_
.c_str()));
174 tank
->setDeathAction((Weapon
*) action
->getAction());
176 if (burnaction_
.c_str()[0] && 0 != strcmp(burnaction_
.c_str(), "none"))
178 Accessory
*action
= context
.getAccessoryStore().
179 findByPrimaryAccessoryName(burnaction_
.c_str());
180 if (!action
|| action
->getType() != AccessoryPart::AccessoryWeapon
)
182 S3D::dialogExit("Scorched3D",
183 S3D::formatStringBuffer("Failed to find burn action \"%s\"",
184 burnaction_
.c_str()));
187 tank
->setBurnAction((Weapon
*) action
->getAction());
190 tank
->getLife().setTargetPosition(position
);
192 groups_
.addToGroups(context
, &tank
->getGroup(), false);