00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038
00039 #include "stratagus.h"
00040 #include "video.h"
00041 #include "missile.h"
00042 #include "script.h"
00043 #include "unit.h"
00044 #include "unit_manager.h"
00045 #include "particle.h"
00046 #include "luacallback.h"
00047
00048
00049
00050
00051
00055 static const char *MissileClassNames[] = {
00056 "missile-class-none",
00057 "missile-class-point-to-point",
00058 "missile-class-point-to-point-with-hit",
00059 "missile-class-point-to-point-cycle-once",
00060 "missile-class-point-to-point-bounce",
00061 "missile-class-stay",
00062 "missile-class-cycle-once",
00063 "missile-class-fire",
00064 "missile-class-hit",
00065 "missile-class-parabolic",
00066 NULL
00067 };
00068
00069
00070
00071
00072
00078 static int CclDefineMissileType(lua_State *l)
00079 {
00080 const char *value;
00081 const char *str;
00082 MissileType *mtype;
00083 unsigned i;
00084 std::string file;
00085
00086 LuaCheckArgs(l, 2);
00087 if (!lua_istable(l, 2)) {
00088 LuaError(l, "incorrect argument");
00089 }
00090
00091
00092
00093 str = LuaToString(l, 1);
00094 mtype = MissileTypeByIdent(str);
00095
00096 if (mtype) {
00097 DebugPrint("Redefining missile-type `%s'\n" _C_ str);
00098 } else {
00099 mtype = NewMissileTypeSlot(str);
00100 }
00101
00102 mtype->NumDirections = 1;
00103 mtype->Flip = true;
00104
00105 mtype->SplashFactor = 100;
00106
00107
00108
00109
00110 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
00111 value = LuaToString(l, -2);
00112 if (!strcmp(value, "File")) {
00113 file = LuaToString(l, -1);
00114 } else if (!strcmp(value, "Size")) {
00115 if (!lua_istable(l, -1) || lua_objlen(l, -1) != 2) {
00116 LuaError(l, "incorrect argument");
00117 }
00118 lua_rawgeti(l, -1, 1);
00119 mtype->Width = LuaToNumber(l, -1);
00120 lua_pop(l, 1);
00121 lua_rawgeti(l, -1, 2);
00122 mtype->Height = LuaToNumber(l, -1);
00123 lua_pop(l, 1);
00124 } else if (!strcmp(value, "Frames")) {
00125 mtype->SpriteFrames = LuaToNumber(l, -1);
00126 } else if (!strcmp(value, "Flip")) {
00127 mtype->Flip = LuaToBoolean(l, -1);
00128 } else if (!strcmp(value, "NumDirections")) {
00129 mtype->NumDirections = LuaToNumber(l, -1);
00130 } else if (!strcmp(value, "transparency")) {
00131 mtype->Transparency = LuaToNumber(l, -1);
00132 } else if (!strcmp(value, "FiredSound")) {
00133 mtype->FiredSound.Name = LuaToString(l, -1);
00134 } else if (!strcmp(value, "ImpactSound")) {
00135 mtype->ImpactSound.Name = LuaToString(l, -1);
00136 } else if (!strcmp(value, "Class")) {
00137 value = LuaToString(l, -1);
00138 for (i = 0; MissileClassNames[i]; ++i) {
00139 if (!strcmp(value, MissileClassNames[i])) {
00140 mtype->Class = i;
00141 break;
00142 }
00143 }
00144 if (!MissileClassNames[i]) {
00145 LuaError(l, "Unsupported class: %s" _C_ value);
00146 }
00147 } else if (!strcmp(value, "NumBounces")) {
00148 mtype->NumBounces = LuaToNumber(l, -1);
00149 } else if (!strcmp(value, "Delay")) {
00150 mtype->StartDelay = LuaToNumber(l, -1);
00151 } else if (!strcmp(value, "Sleep")) {
00152 mtype->Sleep = LuaToNumber(l, -1);
00153 } else if (!strcmp(value, "Speed")) {
00154 mtype->Speed = LuaToNumber(l, -1);
00155 } else if (!strcmp(value, "DrawLevel")) {
00156 mtype->DrawLevel = LuaToNumber(l, -1);
00157 } else if (!strcmp(value, "Range")) {
00158 mtype->Range = LuaToNumber(l, -1);
00159 } else if (!strcmp(value, "ImpactMissile")) {
00160 mtype->ImpactName = LuaToString(l, -1);
00161 } else if (!strcmp(value, "SmokeMissile")) {
00162 mtype->SmokeName = LuaToString(l, -1);
00163 } else if (!strcmp(value, "ImpactParticle")) {
00164 mtype->ImpactParticle = new LuaCallback(l, -1);
00165 } else if (!strcmp(value, "CanHitOwner")) {
00166 mtype->CanHitOwner = LuaToBoolean(l, -1);
00167 } else if (!strcmp(value, "FriendlyFire")) {
00168 mtype->FriendlyFire = LuaToBoolean(l, -1);
00169 } else if (!strcmp(value, "SplashFactor")) {
00170 mtype->SplashFactor = LuaToNumber(l, -1);
00171 } else {
00172 LuaError(l, "Unsupported tag: %s" _C_ value);
00173 }
00174 }
00175
00176 if (!file.empty()) {
00177 mtype->G = CGraphic::New(file, mtype->Width, mtype->Height);
00178 }
00179
00180 return 0;
00181 }
00182
00188 static int CclMissile(lua_State *l)
00189 {
00190 const char *value;
00191 MissileType *type;
00192 int x;
00193 int y;
00194 int dx;
00195 int dy;
00196 int sx;
00197 int sy;
00198 Missile *missile;
00199 int args;
00200 int j;
00201
00202 missile = NULL;
00203 type = NULL;
00204 x = dx = y = dy = sx = sy = -1;
00205
00206 args = lua_gettop(l);
00207 for (j = 0; j < args; ++j) {
00208 value = LuaToString(l, j + 1);
00209 ++j;
00210
00211 if (!strcmp(value, "type")) {
00212 type = MissileTypeByIdent(LuaToString(l, j + 1));
00213 } else if (!strcmp(value, "pos")) {
00214 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00215 LuaError(l, "incorrect argument");
00216 }
00217 lua_rawgeti(l, j + 1, 1);
00218 x = LuaToNumber(l, -1);
00219 lua_pop(l, 1);
00220 lua_rawgeti(l, j + 1, 2);
00221 y = LuaToNumber(l, -1);
00222 lua_pop(l, 1);
00223 } else if (!strcmp(value, "origin-pos")) {
00224 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00225 LuaError(l, "incorrect argument");
00226 }
00227 lua_rawgeti(l, j + 1, 1);
00228 sx = LuaToNumber(l, -1);
00229 lua_pop(l, 1);
00230 lua_rawgeti(l, j + 1, 2);
00231 sy = LuaToNumber(l, -1);
00232 lua_pop(l, 1);
00233 } else if (!strcmp(value, "goal")) {
00234 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00235 LuaError(l, "incorrect argument");
00236 }
00237 lua_rawgeti(l, j + 1, 1);
00238 dx = LuaToNumber(l, -1);
00239 lua_pop(l, 1);
00240 lua_rawgeti(l, j + 1, 2);
00241 dy = LuaToNumber(l, -1);
00242 lua_pop(l, 1);
00243 } else if (!strcmp(value, "local")) {
00244 Assert(type);
00245 missile = MakeLocalMissile(type, x, y, dx, dy);
00246 missile->Local = 1;
00247 --j;
00248 } else if (!strcmp(value, "global")) {
00249 Assert(type);
00250 missile = MakeMissile(type, x, y, dx, dy);
00251 missile->X = x;
00252 missile->Y = y;
00253 missile->SourceX = sx;
00254 missile->SourceY = sy;
00255 missile->DX = dx;
00256 missile->DY = dy;
00257 missile->Local = 0;
00258 --j;
00259 } else if (!strcmp(value, "frame")) {
00260 Assert(missile);
00261 missile->SpriteFrame = LuaToNumber(l, j + 1);
00262 } else if (!strcmp(value, "state")) {
00263 Assert(missile);
00264 missile->State = LuaToNumber(l, j + 1);
00265 } else if (!strcmp(value, "anim-wait")) {
00266 Assert(missile);
00267 missile->AnimWait = LuaToNumber(l, j + 1);
00268 } else if (!strcmp(value, "wait")) {
00269 Assert(missile);
00270 missile->Wait = LuaToNumber(l, j + 1);
00271 } else if (!strcmp(value, "delay")) {
00272 Assert(missile);
00273 missile->Delay = LuaToNumber(l, j + 1);
00274 } else if (!strcmp(value, "source")) {
00275 Assert(missile);
00276 value = LuaToString(l, j + 1);
00277 missile->SourceUnit = UnitSlots[strtol(value + 1, 0, 16)];
00278 missile->SourceUnit->RefsIncrease();
00279 } else if (!strcmp(value, "target")) {
00280 Assert(missile);
00281 value = LuaToString(l, j + 1);
00282 missile->TargetUnit = UnitSlots[strtol(value + 1, 0, 16)];
00283 missile->TargetUnit->RefsIncrease();
00284 } else if (!strcmp(value, "damage")) {
00285 Assert(missile);
00286 missile->Damage = LuaToNumber(l, j + 1);
00287 } else if (!strcmp(value, "ttl")) {
00288 Assert(missile);
00289 missile->TTL = LuaToNumber(l, j + 1);
00290 } else if (!strcmp(value, "hidden")) {
00291 Assert(missile);
00292 missile->Hidden = 1;
00293 --j;
00294 } else if (!strcmp(value, "step")) {
00295 Assert(missile);
00296 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00297 LuaError(l, "incorrect argument");
00298 }
00299 lua_rawgeti(l, j + 1, 1);
00300 missile->CurrentStep = LuaToNumber(l, -1);
00301 lua_pop(l, 1);
00302 lua_rawgeti(l, j + 1, 2);
00303 missile->TotalStep = LuaToNumber(l, -1);
00304 lua_pop(l, 1);
00305 } else {
00306 LuaError(l, "Unsupported tag: %s" _C_ value);
00307 }
00308 }
00309
00310
00311
00312
00313
00314 missile->X = x;
00315 missile->Y = y;
00316 missile->SourceX = sx;
00317 missile->SourceY = sy;
00318 missile->DX = dx;
00319 missile->DY = dy;
00320 return 0;
00321 }
00322
00328 static int CclDefineBurningBuilding(lua_State *l)
00329 {
00330 for (std::vector<BurningBuildingFrame *>::iterator i = BurningBuildingFrames.begin();
00331 i != BurningBuildingFrames.end(); ++i) {
00332 delete *i;
00333 }
00334 BurningBuildingFrames.clear();
00335
00336 int args = lua_gettop(l);
00337 for (int j = 0; j < args; ++j) {
00338 if (!lua_istable(l, j + 1)) {
00339 LuaError(l, "incorrect argument");
00340 }
00341
00342 const char *value;
00343 BurningBuildingFrame *ptr = new BurningBuildingFrame;
00344 int subargs = lua_objlen(l, j + 1);
00345
00346 for (int k = 0; k < subargs; ++k) {
00347 lua_rawgeti(l, j + 1, k + 1);
00348 value = LuaToString(l, -1);
00349 lua_pop(l, 1);
00350 ++k;
00351
00352 if (!strcmp(value, "percent")) {
00353 lua_rawgeti(l, j + 1, k + 1);
00354 ptr->Percent = LuaToNumber(l, -1);
00355 lua_pop(l, 1);
00356 } else if (!strcmp(value, "missile")) {
00357 lua_rawgeti(l, j + 1, k + 1);
00358 ptr->Missile = MissileTypeByIdent(LuaToString(l, -1));
00359 lua_pop(l, 1);
00360 }
00361 }
00362 BurningBuildingFrames.insert(BurningBuildingFrames.begin(), ptr);
00363 }
00364 return 0;
00365 }
00366
00370 void MissileCclRegister(void)
00371 {
00372 lua_register(Lua, "DefineMissileType", CclDefineMissileType);
00373 lua_register(Lua, "Missile", CclMissile);
00374 lua_register(Lua, "DefineBurningBuilding", CclDefineBurningBuilding);
00375 }
00376