[+] Added new RadialParticle
[+] Make particles more configurable from Lua [+] Added 'g' flag for ParseAnimInt to get flag for target unit [+] Added MissileOffsets array which allows more correct placing for missile's starting point (not from unit's center, but from cannon's hole etc.) [+] Added CclGetUnitBoolFlag to get unit's bool-flags in Lua [+] Removed speedup variables (SpeedResourcesHarvest, SpeedResourcesReturn, SpeedBuild, SpeedTrain, SpeedUpgrade, SpeedResearch) into player's code, now speedup could be set individually for each player [+] Added CUpgradeModifier::ModifyPercent for modifying variables by percent, not by const value. [+] Added MissileType::Pierce to allow missiles damage everything on their way [+] Added map preview image generation function for editor (not ready for OpenGL yet) [+] Added flag for CclCreateMissile to control missile's damage [*] Missiles now fly into unit's center (according to the comment in code, the old behaviour was to be used for bunkers) [-] Fixed random number generation code in animations [-] Fixed "Flushing removed unit" message for boarded units [-] Fixed unit death into container (happens when unit is temporary) [-] Fixed land-only restriction for transporters [-] Fixed "spell-cast" mouse action for non-enemy units (now it's possible to use this action for medics) [-] Fixed compilation for MSVC9
This commit is contained in:
parent
98bc02d104
commit
dde984d690
38 changed files with 647 additions and 158 deletions
|
@ -213,6 +213,7 @@ set(particle_SRCS
|
|||
src/particle/graphicanimation.cpp
|
||||
src/particle/chunkparticle.cpp
|
||||
src/particle/particlemanager.cpp
|
||||
src/particle/radialparticle.cpp
|
||||
src/particle/smokeparticle.cpp
|
||||
src/particle/staticparticle.cpp
|
||||
)
|
||||
|
|
|
@ -351,7 +351,7 @@ void COrder_Built::Progress(CUnit &unit, int amount)
|
|||
Boost(unit, amount, HP_INDEX);
|
||||
Boost(unit, amount, SHIELD_INDEX);
|
||||
|
||||
this->ProgressCounter += amount * SpeedBuild;
|
||||
this->ProgressCounter += amount * unit.Player->SpeedBuild / SPEEDUP_FACTOR;
|
||||
UpdateConstructionFrame(unit);
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ void COrder_Built::ProgressHp(CUnit &unit, int amount)
|
|||
{
|
||||
Boost(unit, amount, HP_INDEX);
|
||||
|
||||
this->ProgressCounter += amount * SpeedBuild;
|
||||
this->ProgressCounter += amount * unit.Player->SpeedBuild / SPEEDUP_FACTOR;
|
||||
UpdateConstructionFrame(unit);
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ void COrder_Built::Boost(CUnit &building, int amount, int varIndex) const
|
|||
|
||||
const int costs = building.Stats->Costs[TimeCost] * 600;
|
||||
const int progress = this->ProgressCounter;
|
||||
const int newProgress = progress + amount * SpeedBuild;
|
||||
const int newProgress = progress + amount * building.Player->SpeedBuild / SPEEDUP_FACTOR;
|
||||
const int maxValue = building.Variable[varIndex].Max;
|
||||
|
||||
int ¤tValue = building.Variable[varIndex].Value;
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
}
|
||||
#endif
|
||||
CPlayer &player = *unit.Player;
|
||||
player.UpgradeTimers.Upgrades[upgrade.ID] += SpeedResearch;
|
||||
player.UpgradeTimers.Upgrades[upgrade.ID] += player.SpeedResearch / SPEEDUP_FACTOR;
|
||||
if (player.UpgradeTimers.Upgrades[upgrade.ID] >= upgrade.Costs[TimeCost]) {
|
||||
player.Notify(NotifyGreen, unit.tilePos, _("%s: research complete"), type.Name.c_str());
|
||||
if (&player == ThisPlayer) {
|
||||
|
|
|
@ -474,7 +474,7 @@ int COrder_Resource::StartGathering(CUnit &unit)
|
|||
#endif
|
||||
UnitHeadingFromDeltaXY(unit, this->goalPos - unit.tilePos);
|
||||
if (resinfo.WaitAtResource) {
|
||||
this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
|
||||
this->TimeToHarvest = resinfo.WaitAtResource / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId] / SPEEDUP_FACTOR;
|
||||
} else {
|
||||
this->TimeToHarvest = 1;
|
||||
}
|
||||
|
@ -542,7 +542,7 @@ int COrder_Resource::StartGathering(CUnit &unit)
|
|||
goal->Resource.Active++;
|
||||
|
||||
if (resinfo.WaitAtResource) {
|
||||
this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
|
||||
this->TimeToHarvest = resinfo.WaitAtResource / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId] / SPEEDUP_FACTOR;
|
||||
} else {
|
||||
this->TimeToHarvest = 1;
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ int COrder_Resource::GatherResource(CUnit &unit)
|
|||
while (!this->DoneHarvesting && this->TimeToHarvest < 0) {
|
||||
//FIXME: rb - how should it look for WaitAtResource == 0
|
||||
if (resinfo.WaitAtResource) {
|
||||
this->TimeToHarvest += resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
|
||||
this->TimeToHarvest += resinfo.WaitAtResource / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId] / SPEEDUP_FACTOR;
|
||||
} else {
|
||||
this->TimeToHarvest += 1;
|
||||
}
|
||||
|
@ -965,7 +965,7 @@ int COrder_Resource::MoveToDepot(CUnit &unit)
|
|||
unit.CurrentResource = 0;
|
||||
|
||||
if (unit.Wait) {
|
||||
unit.Wait /= SpeedResourcesReturn[resinfo.ResourceId];
|
||||
unit.Wait /= unit.Player->SpeedResourcesReturn[resinfo.ResourceId] / SPEEDUP_FACTOR;
|
||||
if (unit.Wait) {
|
||||
unit.Wait--;
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ static void AnimateActionTrain(CUnit &unit)
|
|||
CPlayer &player = *unit.Player;
|
||||
const CUnitType &nType = *this->Type;
|
||||
const int cost = nType.Stats[player.Index].Costs[TimeCost];
|
||||
this->Ticks += SpeedTrain;
|
||||
this->Ticks += player.SpeedTrain / SPEEDUP_FACTOR;
|
||||
|
||||
if (this->Ticks < cost) {
|
||||
unit.Wait = CYCLES_PER_SECOND / 6;
|
||||
|
|
|
@ -266,7 +266,7 @@ static void AnimateActionUpgradeTo(CUnit &unit)
|
|||
const CUnitType &newtype = *this->Type;
|
||||
const CUnitStats &newstats = newtype.Stats[player.Index];
|
||||
|
||||
this->Ticks += SpeedUpgrade;
|
||||
this->Ticks += player.SpeedUpgrade / SPEEDUP_FACTOR;
|
||||
if (this->Ticks < newstats.Costs[TimeCost]) {
|
||||
unit.Wait = CYCLES_PER_SECOND / 6;
|
||||
return ;
|
||||
|
|
|
@ -283,6 +283,7 @@ static void HandleBuffs(CUnit &unit, int amount)
|
|||
unit.Variable[HP_INDEX].Value -= amount;
|
||||
if (unit.Variable[HP_INDEX].Value <= 0) {
|
||||
LetUnitDie(unit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +344,7 @@ static void HandleUnitAction(CUnit &unit)
|
|||
// o Or the order queue should be flushed.
|
||||
if ((unit.Orders[0]->Action == UnitActionStandGround || unit.Orders[0]->Finished)
|
||||
&& unit.Orders.size() > 1) {
|
||||
if (unit.Removed) { // FIXME: johns I see this as an error
|
||||
if (unit.Removed && unit.Orders[0]->Action != UnitActionBoard) { // FIXME: johns I see this as an error
|
||||
DebugPrint("Flushing removed unit\n");
|
||||
// This happens, if building with ALT+SHIFT.
|
||||
return;
|
||||
|
|
|
@ -177,7 +177,14 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
return goal->Variable[index].Value * 100 / goal->Variable[index].Max;
|
||||
}
|
||||
return 0;
|
||||
} else if ((s[0] == 'b') && unit != NULL) { //unit bool flag detected
|
||||
} else if ((s[0] == 'b' || s[0] == 'g') && unit != NULL) { //unit bool flag detected
|
||||
if (s[0] == 'g') {
|
||||
if (unit->CurrentOrder()->HasGoal()) {
|
||||
goal = unit->CurrentOrder()->GetGoal();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
const int index = UnitTypeVar.BoolFlagNameLookup[cur];// User bool flags
|
||||
if (index == -1) {
|
||||
fprintf(stderr, "Bad bool-flag name '%s'\n", cur);
|
||||
|
@ -209,10 +216,11 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
} else if (s[0] == 'r') { //random value
|
||||
char *next = strchr(cur, '.');
|
||||
if (next == NULL) {
|
||||
return SyncRand(atoi(cur));
|
||||
return SyncRand(atoi(cur) + 1);
|
||||
} else {
|
||||
*next = '\0';
|
||||
return atoi(cur) + SyncRand(atoi(next + 1));
|
||||
const int min = atoi(cur);
|
||||
return min + SyncRand(atoi(next + 1) - min + 1);
|
||||
}
|
||||
} else if (s[0] == 'l') { //player number
|
||||
return ParseAnimPlayer(*unit, cur);
|
||||
|
|
|
@ -99,7 +99,10 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
const int destx = ParseAnimInt(&unit, this->destXStr.c_str());
|
||||
const int desty = ParseAnimInt(&unit, this->destYStr.c_str());
|
||||
const int flags = ParseAnimFlags(unit, this->flagsStr.c_str());
|
||||
const int offsetnum = ParseAnimInt(&unit, this->offsetNumStr.c_str());
|
||||
const CUnit *goal = flags & ANIM_SM_RELTARGET ? unit.CurrentOrder()->GetGoal() : &unit;
|
||||
const int dir = ((goal->Direction + NextDirection / 2) & 0xFF) / NextDirection;
|
||||
const PixelPos moff = goal->Type->MissileOffsets[dir][!offsetnum ? 0 : offsetnum - 1];
|
||||
PixelPos start;
|
||||
PixelPos dest;
|
||||
|
||||
|
@ -107,11 +110,11 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
return;
|
||||
}
|
||||
if ((flags & ANIM_SM_PIXEL)) {
|
||||
start.x = goal->tilePos.x * PixelTileSize.x + goal->IX + startx;
|
||||
start.y = goal->tilePos.y * PixelTileSize.y + goal->IY + starty;
|
||||
start.x = goal->tilePos.x * PixelTileSize.x + goal->IX + moff.x + startx;
|
||||
start.y = goal->tilePos.y * PixelTileSize.y + goal->IY + moff.y + starty;
|
||||
} else {
|
||||
start.x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
start.y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
start.x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2 + moff.x;
|
||||
start.y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2 + moff.y;
|
||||
}
|
||||
if ((flags & ANIM_SM_TOTARGET)) {
|
||||
CUnit *target = goal->CurrentOrder()->GetGoal();
|
||||
|
@ -186,6 +189,10 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
begin = std::min(len, str.find_first_not_of(' ', end));
|
||||
end = std::min(len, str.find(' ', begin));
|
||||
this->flagsStr.assign(str, begin, end - begin);
|
||||
|
||||
begin = std::min(len, str.find_first_not_of(' ', end));
|
||||
end = std::min(len, str.find(' ', begin));
|
||||
this->offsetNumStr.assign(str, begin, end - begin);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "actions.h"
|
||||
|
@ -168,6 +170,115 @@ static void LoadStratagusMap(const std::string &smpname, const std::string &mapn
|
|||
Map.Info.Filename = mapname;
|
||||
}
|
||||
|
||||
// Write a small image of map preview
|
||||
static void WriteMapPreview(const char *mapname, CMap &map)
|
||||
{
|
||||
FILE *fp = fopen(mapname, "wb");
|
||||
if (fp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
fclose(fp);
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
/* If we get here, we had a problem reading the file */
|
||||
fclose(fp);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set up the output control if you are using standard C streams */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, UI.Minimap.W, UI.Minimap.H, 8,
|
||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
if (UseOpenGL) {
|
||||
unsigned char *pixels = new unsigned char[UI.Minimap.W * UI.Minimap.H * 3];
|
||||
if (!pixels) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifndef USE_GLES
|
||||
glReadBuffer(GL_FRONT);
|
||||
#endif
|
||||
glReadPixels(UI.Minimap.X, UI.Minimap.Y, UI.Minimap.W, UI.Minimap.H, GL_RGB, GL_UNSIGNED_BYTE, pixels);
|
||||
for (int i = 0; i < UI.Minimap.H; ++i) {
|
||||
png_write_row(png_ptr, pixels + (UI.Minimap.H - 1 - i) * UI.Minimap.W * 3);
|
||||
}
|
||||
delete[] pixels;
|
||||
} else {
|
||||
unsigned char *row = new unsigned char[UI.Minimap.W * 3];
|
||||
const SDL_PixelFormat *fmt = MinimapSurface->format;
|
||||
SDL_Surface *preview = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
UI.Minimap.W, UI.Minimap.H, 32, fmt->Rmask, fmt->Gmask, fmt->Bmask, 0);
|
||||
SDL_BlitSurface(MinimapSurface, NULL, preview, NULL);
|
||||
|
||||
SDL_LockSurface(preview);
|
||||
|
||||
SDL_Rect rect;
|
||||
const unsigned int rectSize = 5;
|
||||
for (int i = 0; i < PlayerMax - 1; ++i) {
|
||||
if (Players[i].Type != PlayerNobody) {
|
||||
rect.x = Players[i].StartPos.x * UI.Minimap.W / map.Info.MapWidth - rectSize / 2;
|
||||
rect.y = Players[i].StartPos.y * UI.Minimap.H / map.Info.MapHeight - rectSize / 2;
|
||||
rect.w = rect.h = rectSize;
|
||||
SDL_FillRect(preview, &rect, Players[i].Color);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < UI.Minimap.H; ++i) {
|
||||
switch (preview->format->BytesPerPixel) {
|
||||
case 1:
|
||||
for (int j = 0; j < UI.Minimap.W; ++j) {
|
||||
Uint8 c = ((Uint8 *)preview->pixels)[j + i * UI.Minimap.W];
|
||||
row[j * 3 + 0] = fmt->palette->colors[c].r;
|
||||
row[j * 3 + 1] = fmt->palette->colors[c].g;
|
||||
row[j * 3 + 2] = fmt->palette->colors[c].b;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
memcpy(row, (char *)preview->pixels + i * UI.Minimap.W, UI.Minimap.W * 3);
|
||||
break;
|
||||
case 4:
|
||||
for (int j = 0; j < UI.Minimap.W; ++j) {
|
||||
Uint32 c = ((Uint32 *)preview->pixels)[j + i * UI.Minimap.W];
|
||||
row[j * 3 + 0] = ((c & fmt->Rmask) >> fmt->Rshift);
|
||||
row[j * 3 + 1] = ((c & fmt->Gmask) >> fmt->Gshift);
|
||||
row[j * 3 + 2] = ((c & fmt->Bmask) >> fmt->Bshift);
|
||||
}
|
||||
break;
|
||||
}
|
||||
png_write_row(png_ptr, row);
|
||||
}
|
||||
delete[] row;
|
||||
|
||||
SDL_UnlockSurface(preview);
|
||||
SDL_FreeSurface(preview);
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* clean up after the write, and free any memory allocated */
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
// Write the map presentation file
|
||||
static int WriteMapPresentation(const std::string &mapname, CMap &map, char *)
|
||||
|
@ -282,6 +393,7 @@ int WriteMapSetup(const char *mapSetup, CMap &map, int writeTerrain)
|
|||
}
|
||||
|
||||
f->printf("-- place units\n");
|
||||
f->printf("if (MapUnitsInit ~= nil) then MapUnitsInit() end\n");
|
||||
for (CUnitManager::Iterator it = UnitManager.begin(); it != UnitManager.end(); ++it) {
|
||||
CUnit &unit = **it;
|
||||
f->printf("unit = CreateUnit(\"%s\", %d, {%d, %d})\n",
|
||||
|
@ -315,7 +427,9 @@ int WriteMapSetup(const char *mapSetup, CMap &map, int writeTerrain)
|
|||
int SaveStratagusMap(const std::string &mapName, CMap &map, int writeTerrain)
|
||||
{
|
||||
char mapSetup[PATH_MAX];
|
||||
char *extension;
|
||||
char previewName[PATH_MAX];
|
||||
char *setupExtension;
|
||||
char *previewExtension;
|
||||
|
||||
if (!map.Info.MapWidth || !map.Info.MapHeight) {
|
||||
fprintf(stderr, "%s: invalid Stratagus map\n", mapName.c_str());
|
||||
|
@ -323,12 +437,17 @@ int SaveStratagusMap(const std::string &mapName, CMap &map, int writeTerrain)
|
|||
}
|
||||
|
||||
strcpy_s(mapSetup, sizeof(mapSetup), mapName.c_str());
|
||||
extension = strstr(mapSetup, ".smp");
|
||||
if (!extension) {
|
||||
setupExtension = strstr(mapSetup, ".smp");
|
||||
if (!setupExtension) {
|
||||
fprintf(stderr, "%s: invalid Statagus map filename\n", mapName.c_str());
|
||||
}
|
||||
memcpy(extension, ".sms", 4 * sizeof(char));
|
||||
|
||||
strcpy_s(previewName, sizeof(previewName), mapName.c_str());
|
||||
previewExtension = strstr(previewName, ".smp");
|
||||
memcpy(previewExtension, ".png\0", 5 * sizeof(char));
|
||||
WriteMapPreview(previewName, map);
|
||||
|
||||
memcpy(setupExtension, ".sms", 4 * sizeof(char));
|
||||
if (WriteMapPresentation(mapName, map, mapSetup) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -910,50 +1029,54 @@ static int CclGetGodMode(lua_State *l)
|
|||
}
|
||||
|
||||
/**
|
||||
** Set resource harvesting speed.
|
||||
** Set resource harvesting speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedResourcesHarvest(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 2);
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const std::string resource = LuaToString(l, 1);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
const std::string resource = LuaToString(l, 2);
|
||||
const int resId = GetResourceIdByName(l, resource.c_str());
|
||||
|
||||
SpeedResourcesHarvest[resId] = LuaToNumber(l, 2);
|
||||
Players[player].SpeedResourcesHarvest[resId] = LuaToNumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set resource returning speed.
|
||||
** Set resource returning speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedResourcesReturn(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 2);
|
||||
const std::string resource = LuaToString(l, 1);
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const int player = LuaToNumber(l, 1);
|
||||
const std::string resource = LuaToString(l, 2);
|
||||
const int resId = GetResourceIdByName(l, resource.c_str());
|
||||
|
||||
SpeedResourcesReturn[resId] = LuaToNumber(l, 2);
|
||||
Players[player].SpeedResourcesReturn[resId] = LuaToNumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set building speed.
|
||||
** Set building speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedBuild(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 1);
|
||||
SpeedBuild = LuaToNumber(l, 1);
|
||||
LuaCheckArgs(l, 2);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
Players[player].SpeedBuild = LuaToNumber(l, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Get building speed.
|
||||
** Get building speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
**
|
||||
|
@ -961,25 +1084,27 @@ static int CclSetSpeedBuild(lua_State *l)
|
|||
*/
|
||||
static int CclGetSpeedBuild(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 0);
|
||||
lua_pushnumber(l, SpeedBuild);
|
||||
LuaCheckArgs(l, 1);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
lua_pushnumber(l, Players[player].SpeedBuild);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set training speed.
|
||||
** Set training speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedTrain(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 1);
|
||||
SpeedTrain = LuaToNumber(l, 1);
|
||||
LuaCheckArgs(l, 2);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
Players[player].SpeedTrain = LuaToNumber(l, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Get training speed.
|
||||
** Get training speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
**
|
||||
|
@ -987,58 +1112,60 @@ static int CclSetSpeedTrain(lua_State *l)
|
|||
*/
|
||||
static int CclGetSpeedTrain(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 0);
|
||||
lua_pushnumber(l, SpeedTrain);
|
||||
LuaCheckArgs(l, 1);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
lua_pushnumber(l, Players[player].SpeedTrain);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** For debug increase upgrading speed.
|
||||
** For debug increase upgrading speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedUpgrade(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 1);
|
||||
SpeedUpgrade = LuaToNumber(l, 1);
|
||||
LuaCheckArgs(l, 2);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
Players[player].SpeedUpgrade = LuaToNumber(l, 2);
|
||||
|
||||
lua_pushnumber(l, SpeedUpgrade);
|
||||
lua_pushnumber(l, Players[player].SpeedUpgrade);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** For debug increase researching speed.
|
||||
** For debug increase researching speed (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeedResearch(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 1);
|
||||
SpeedResearch = LuaToNumber(l, 1);
|
||||
LuaCheckArgs(l, 2);
|
||||
const int player = LuaToNumber(l, 1);
|
||||
Players[player].SpeedResearch = LuaToNumber(l, 2);
|
||||
|
||||
lua_pushnumber(l, SpeedResearch);
|
||||
lua_pushnumber(l, Players[player].SpeedResearch);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** For debug increase all speeds.
|
||||
** For debug increase all speeds (deprecated).
|
||||
**
|
||||
** @param l Lua state.
|
||||
*/
|
||||
static int CclSetSpeeds(lua_State *l)
|
||||
{
|
||||
int i;
|
||||
int s;
|
||||
|
||||
LuaCheckArgs(l, 1);
|
||||
s = LuaToNumber(l, 1);
|
||||
for (i = 0; i < MaxCosts; ++i) {
|
||||
SpeedResourcesHarvest[i] = s;
|
||||
SpeedResourcesReturn[i] = s;
|
||||
const int speed = LuaToNumber(l, 1);
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
for (int j = 0; j < MaxCosts; ++j) {
|
||||
Players[i].SpeedResourcesHarvest[j] = speed;
|
||||
Players[i].SpeedResourcesReturn[j] = speed;
|
||||
}
|
||||
Players[i].SpeedBuild = Players[i].SpeedTrain = Players[i].SpeedUpgrade = Players[i].SpeedResearch = speed;
|
||||
}
|
||||
SpeedBuild = SpeedTrain = SpeedUpgrade = SpeedResearch = s;
|
||||
|
||||
lua_pushnumber(l, s);
|
||||
lua_pushnumber(l, speed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,17 +148,6 @@ int SaveGame(const std::string &filename)
|
|||
|
||||
file.printf("SetGodMode(%s)\n", GodMode ? "true" : "false");
|
||||
|
||||
for (unsigned int i = 0; i < MaxCosts; ++i) {
|
||||
file.printf("SetSpeedResourcesHarvest(\"%s\", %d)\n",
|
||||
DefaultResourceNames[i].c_str(), SpeedResourcesHarvest[i]);
|
||||
file.printf("SetSpeedResourcesReturn(\"%s\", %d)\n",
|
||||
DefaultResourceNames[i].c_str(), SpeedResourcesReturn[i]);
|
||||
}
|
||||
file.printf("SetSpeedBuild(%d)\n", SpeedBuild);
|
||||
file.printf("SetSpeedTrain(%d)\n", SpeedTrain);
|
||||
file.printf("SetSpeedUpgrade(%d)\n", SpeedUpgrade);
|
||||
file.printf("SetSpeedResearch(%d)\n", SpeedResearch);
|
||||
|
||||
SaveUnitTypes(file);
|
||||
SaveUpgrades(file);
|
||||
SavePlayers(file);
|
||||
|
|
|
@ -50,6 +50,7 @@ private:
|
|||
std::string destXStr;
|
||||
std::string destYStr;
|
||||
std::string flagsStr;
|
||||
std::string offsetNumStr;
|
||||
};
|
||||
|
||||
//@}
|
||||
|
|
|
@ -85,6 +85,15 @@ public:
|
|||
bool UpdateCache;
|
||||
};
|
||||
|
||||
// Minimap surface with units (for OpenGL)
|
||||
extern unsigned char *MinimapSurfaceGL;
|
||||
// Minimap surface with terrain only (for OpenGL)
|
||||
extern unsigned char *MinimapTerrainSurfaceGL;
|
||||
// Minimap surface with units (for software)
|
||||
extern SDL_Surface *MinimapSurface;
|
||||
// Minimap surface with terrain only (for software)
|
||||
extern SDL_Surface *MinimapTerrainSurface;
|
||||
|
||||
//@}
|
||||
|
||||
#endif // !__MINIMAP_H__
|
||||
|
|
|
@ -373,6 +373,7 @@ public:
|
|||
bool CanHitOwner; /// missile can hit the owner
|
||||
bool FriendlyFire; /// missile can't hit own units
|
||||
bool AlwaysFire; /// missile will always fire (even if target is dead)
|
||||
bool Pierce; /// missile will hit every unit on his way
|
||||
|
||||
int Class; /// missile class
|
||||
int NumBounces; /// number of bounces
|
||||
|
|
|
@ -125,7 +125,8 @@ protected:
|
|||
class CChunkParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CChunkParticle(CPosition position, Animation *smokeAnimation);
|
||||
CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation,
|
||||
int minVelocity, int maxVelocity, int minTrajectoryAngle);
|
||||
virtual ~CChunkParticle();
|
||||
|
||||
virtual void draw();
|
||||
|
@ -139,7 +140,11 @@ protected:
|
|||
int nextSmokeTicks;
|
||||
int lifetime;
|
||||
int age;
|
||||
int minVelocity;
|
||||
int maxVelocity;
|
||||
int minTrajectoryAngle;
|
||||
float height;
|
||||
Animation *debrisAnimation;
|
||||
Animation *smokeAnimation;
|
||||
|
||||
struct {
|
||||
|
@ -164,6 +169,23 @@ protected:
|
|||
Animation *puff;
|
||||
};
|
||||
|
||||
class CRadialParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CRadialParticle(CPosition position, Animation *animation, int maxSpeed);
|
||||
virtual ~CRadialParticle();
|
||||
|
||||
virtual void draw();
|
||||
virtual void update(int ticks);
|
||||
virtual CParticle *clone();
|
||||
|
||||
protected:
|
||||
Animation *animation;
|
||||
float direction;
|
||||
int speed;
|
||||
int maxSpeed;
|
||||
};
|
||||
|
||||
|
||||
class CParticleManager
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#define STORE_BUILDING 1
|
||||
#define STORE_BOTH 2
|
||||
|
||||
#define SPEEDUP_FACTOR 100
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -97,6 +98,13 @@ public:
|
|||
int Incomes[MaxCosts]; /// income of the resources
|
||||
int Revenue[MaxCosts]; /// income rate of the resources
|
||||
|
||||
int SpeedResourcesHarvest[MaxCosts]; /// speed factor for harvesting resources
|
||||
int SpeedResourcesReturn[MaxCosts]; /// speed factor for returning resources
|
||||
int SpeedBuild; /// speed factor for building
|
||||
int SpeedTrain; /// speed factor for training
|
||||
int SpeedUpgrade; /// speed factor for upgrading
|
||||
int SpeedResearch; /// speed factor for researching
|
||||
|
||||
// FIXME: shouldn't use the constant
|
||||
int UnitTypesCount[UnitTypeMax]; /// total units of unit-type
|
||||
|
||||
|
|
|
@ -59,7 +59,9 @@
|
|||
#endif
|
||||
|
||||
#define snprintf _snprintf
|
||||
#if !(_MSC_VER >= 1500 && _MSC_VER < 1600)
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#define unlink _unlink
|
||||
#define strdup _strdup
|
||||
#define strcasecmp _stricmp
|
||||
|
@ -208,11 +210,6 @@ extern std::string ClickMissile; /// Missile to show when you click
|
|||
extern std::string DamageMissile; /// Missile to show damage caused
|
||||
extern std::string MenuRace;
|
||||
|
||||
extern int SpeedBuild; /// Speed factor for building
|
||||
extern int SpeedTrain; /// Speed factor for training
|
||||
extern int SpeedUpgrade; /// Speed factor for upgrading
|
||||
extern int SpeedResearch; /// Speed factor for researching
|
||||
|
||||
extern bool UseHPForXp; /// true if gain XP by dealing damage, false if by killing.
|
||||
|
||||
extern unsigned long GameCycle; /// Game simulation cycle counter
|
||||
|
|
|
@ -552,6 +552,9 @@ class Mng;
|
|||
#endif
|
||||
class LuaCallback;
|
||||
|
||||
#define UnitSides 8
|
||||
#define MaxAttackPos 5
|
||||
|
||||
CUnitType *UnitTypeByIdent(const std::string &ident);
|
||||
|
||||
enum GroupSelectionMode {
|
||||
|
@ -913,15 +916,16 @@ public:
|
|||
std::string File; /// Sprite files
|
||||
std::string ShadowFile; /// Shadow file
|
||||
|
||||
int Width; /// Sprite width
|
||||
int Height; /// Sprite height
|
||||
int OffsetX; /// Sprite horizontal offset
|
||||
int OffsetY; /// Sprite vertical offset
|
||||
int DrawLevel; /// Level to Draw UnitType at
|
||||
int ShadowWidth; /// Shadow sprite width
|
||||
int ShadowHeight; /// Shadow sprite height
|
||||
int ShadowOffsetX; /// Shadow horizontal offset
|
||||
int ShadowOffsetY; /// Shadow vertical offset
|
||||
int Width; /// Sprite width
|
||||
int Height; /// Sprite height
|
||||
int OffsetX; /// Sprite horizontal offset
|
||||
int OffsetY; /// Sprite vertical offset
|
||||
int DrawLevel; /// Level to Draw UnitType at
|
||||
int ShadowWidth; /// Shadow sprite width
|
||||
int ShadowHeight; /// Shadow sprite height
|
||||
int ShadowOffsetX; /// Shadow horizontal offset
|
||||
int ShadowOffsetY; /// Shadow vertical offset
|
||||
PixelPos MissileOffsets[UnitSides][MaxAttackPos]; /// Attack offsets for missiles
|
||||
|
||||
CAnimations *Animations; /// Animation scripts
|
||||
int StillFrame; /// Still frame
|
||||
|
|
|
@ -74,16 +74,6 @@ enum CostType {
|
|||
#define ScoreCost (MaxCosts + 1)
|
||||
#define ManaResCost (MaxCosts + 2)
|
||||
|
||||
/**
|
||||
** Speed factor for harvesting resources
|
||||
*/
|
||||
extern int SpeedResourcesHarvest[MaxCosts];
|
||||
|
||||
/**
|
||||
** Speed factor for returning resources
|
||||
*/
|
||||
extern int SpeedResourcesReturn[MaxCosts];
|
||||
|
||||
/**
|
||||
** Default resources for a new player.
|
||||
*/
|
||||
|
@ -187,15 +177,19 @@ public:
|
|||
class CUpgradeModifier
|
||||
{
|
||||
public:
|
||||
CUpgradeModifier() : UpgradeId(0), ConvertTo(NULL) {
|
||||
CUpgradeModifier() : UpgradeId(0), ConvertTo(NULL), ModifyPercent(NULL) {
|
||||
memset(ChangeUnits, 0, sizeof(ChangeUnits));
|
||||
memset(ChangeUpgrades, 0, sizeof(ChangeUpgrades));
|
||||
memset(ApplyTo, 0, sizeof(ApplyTo));
|
||||
}
|
||||
~CUpgradeModifier() {
|
||||
delete [] this->ModifyPercent;
|
||||
}
|
||||
|
||||
int UpgradeId; /// used to filter required modifier
|
||||
|
||||
CUnitStats Modifier; /// modifier of unit stats.
|
||||
CUnitStats Modifier; /// modifier of unit stats.
|
||||
int *ModifyPercent; /// use for percent modifiers
|
||||
|
||||
// allow/forbid bitmaps -- used as chars for example:
|
||||
// `?' -- leave as is, `F' -- forbid, `A' -- allow
|
||||
|
|
|
@ -66,13 +66,14 @@
|
|||
-- Variables
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
unsigned char *MinimapSurfaceGL;
|
||||
unsigned char *MinimapTerrainSurfaceGL;
|
||||
SDL_Surface *MinimapSurface; /// generated minimap
|
||||
SDL_Surface *MinimapTerrainSurface; /// generated minimap terrain
|
||||
|
||||
static GLuint MinimapTexture;
|
||||
static unsigned char *MinimapSurfaceGL;
|
||||
static unsigned char *MinimapTerrainSurfaceGL;
|
||||
static int MinimapTextureWidth;
|
||||
static int MinimapTextureHeight;
|
||||
static SDL_Surface *MinimapSurface; /// generated minimap
|
||||
static SDL_Surface *MinimapTerrainSurface; /// generated minimap terrain
|
||||
|
||||
static int *Minimap2MapX; /// fast conversion table
|
||||
static int *Minimap2MapY; /// fast conversion table
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "trigger.h"
|
||||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unitsound.h"
|
||||
#include "unittype.h"
|
||||
|
||||
|
@ -376,7 +377,9 @@ void FireMissile(CUnit &unit, CUnit *goal, const Vec2i &goalPos)
|
|||
|
||||
// If Firing from inside a Bunker
|
||||
CUnit *from = GetFirstContainer(unit);
|
||||
const PixelPos startPixelPos = Map.TilePosToMapPixelPos_Center(from->tilePos);
|
||||
const int dir = ((unit.Direction + NextDirection / 2) & 0xFF) / NextDirection;
|
||||
const PixelPos startPixelPos = Map.TilePosToMapPixelPos_Center(from->tilePos)
|
||||
+ unit.Type->MissileOffsets[dir][0];
|
||||
|
||||
Vec2i dpos;
|
||||
if (goal) {
|
||||
|
@ -391,7 +394,12 @@ void FireMissile(CUnit &unit, CUnit *goal, const Vec2i &goalPos)
|
|||
}
|
||||
// Fire to nearest point of the unit!
|
||||
// If Firing from inside a Bunker
|
||||
NearestOfUnit(*goal, GetFirstContainer(unit)->tilePos, &dpos);
|
||||
if (unit.Container) {
|
||||
NearestOfUnit(*goal, GetFirstContainer(unit)->tilePos, &dpos);
|
||||
} else {
|
||||
dpos.x = goal->tilePos.x + goal->Type->TileWidth / 2;
|
||||
dpos.y = goal->tilePos.y + goal->Type->TileHeight / 2;
|
||||
}
|
||||
} else {
|
||||
dpos = newgoalPos;
|
||||
// FIXME: Can this be too near??
|
||||
|
@ -662,6 +670,14 @@ bool PointToPointMissile(Missile &missile)
|
|||
missile.Type->SmokeParticle->run();
|
||||
}
|
||||
|
||||
if (missile.Type->Pierce) {
|
||||
CUnit *unit = UnitOnMapTile(Map.MapPixelPosToTilePos(missile.position), -1);
|
||||
if (unit && unit->IsAliveOnMap()
|
||||
&& (missile.Type->FriendlyFire || unit->IsEnemy(*missile.SourceUnit->Player))) {
|
||||
missile.MissileHit();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1096,8 +1112,8 @@ MissileType::MissileType(const std::string &ident) :
|
|||
Ident(ident), Transparency(0), DrawLevel(0),
|
||||
SpriteFrames(0), NumDirections(0), ChangeVariable(-1), ChangeAmount(0), ChangeMax(false),
|
||||
CorrectSphashDamage(false), Flip(false), CanHitOwner(false), FriendlyFire(false),
|
||||
AlwaysFire(false), Class(), NumBounces(0), StartDelay(0), Sleep(0), Speed(0),
|
||||
Range(0), SplashFactor(0), ImpactParticle(NULL), SmokeParticle(NULL), G(NULL)
|
||||
AlwaysFire(false), Pierce(false), Class(), NumBounces(0), StartDelay(0), Sleep(0),
|
||||
Speed(0), Range(0), SplashFactor(0), ImpactParticle(NULL), SmokeParticle(NULL), G(NULL)
|
||||
{
|
||||
size.x = 0;
|
||||
size.y = 0;
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "missile.h"
|
||||
|
||||
#include "luacallback.h"
|
||||
#include "map.h"
|
||||
#include "unit_find.h"
|
||||
|
||||
/**
|
||||
** Calculate parabolic trajectories.
|
||||
|
@ -86,6 +88,13 @@ static int ParabolicMissile(Missile &missile)
|
|||
missile.Type->SmokeParticle->pushInteger(position.y);
|
||||
missile.Type->SmokeParticle->run();
|
||||
}
|
||||
if (missile.Type->Pierce) {
|
||||
CUnit *unit = UnitOnMapTile(Map.MapPixelPosToTilePos(missile.position), -1);
|
||||
if (unit && unit->IsAliveOnMap()
|
||||
&& (missile.Type->FriendlyFire || unit->IsEnemy(*missile.SourceUnit->Player))) {
|
||||
missile.MissileHit();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "luacallback.h"
|
||||
#include "map.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
|
||||
/**
|
||||
** Handle tracer missile.
|
||||
|
@ -76,6 +77,14 @@ static int TracerMissile(Missile &missile)
|
|||
missile.Type->SmokeParticle->pushInteger(position.y);
|
||||
missile.Type->SmokeParticle->run();
|
||||
}
|
||||
if (missile.Type->Pierce) {
|
||||
Assert(missile.SourceUnit);
|
||||
CUnit *unit = UnitOnMapTile(Map.MapPixelPosToTilePos(missile.position), -1);
|
||||
if (unit && unit->IsAliveOnMap()
|
||||
&& (missile.Type->FriendlyFire || unit->IsEnemy(*missile.SourceUnit->Player))) {
|
||||
missile.MissileHit();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,8 @@ void MissileType::Load(lua_State *l)
|
|||
this->CanHitOwner = LuaToBoolean(l, -1);
|
||||
} else if (!strcmp(value, "AlwaysFire")) {
|
||||
this->AlwaysFire = LuaToBoolean(l, -1);
|
||||
} else if (!strcmp(value, "Pierce")) {
|
||||
this->Pierce = LuaToBoolean(l, -1);
|
||||
} else if (!strcmp(value, "FriendlyFire")) {
|
||||
this->FriendlyFire = LuaToBoolean(l, -1);
|
||||
} else if (!strcmp(value, "SplashFactor")) {
|
||||
|
@ -376,7 +378,7 @@ static int CclDefineBurningBuilding(lua_State *l)
|
|||
*/
|
||||
static int CclCreateMissile(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 5);
|
||||
LuaCheckArgs(l, 6);
|
||||
|
||||
const std::string name = LuaToString(l, 1);
|
||||
const MissileType *mtype = MissileTypeByIdent(name);
|
||||
|
@ -405,6 +407,7 @@ static int CclCreateMissile(lua_State *l)
|
|||
|
||||
const int sourceUnitId = LuaToNumber(l, 4);
|
||||
const int destUnitId = LuaToNumber(l, 5);
|
||||
const bool dealDamage = LuaToBoolean(l, 6);
|
||||
CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : NULL;
|
||||
CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : NULL;
|
||||
|
||||
|
@ -419,7 +422,9 @@ static int CclCreateMissile(lua_State *l)
|
|||
if (!missile) {
|
||||
return 0;
|
||||
}
|
||||
missile->SourceUnit = sourceUnit;
|
||||
if (dealDamage) {
|
||||
missile->SourceUnit = sourceUnit;
|
||||
}
|
||||
missile->TargetUnit = destUnit;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ static inline float deg2rad(int degrees)
|
|||
}
|
||||
|
||||
|
||||
CChunkParticle::CChunkParticle(CPosition position, Animation *smokeAnimation) :
|
||||
CChunkParticle::CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation,
|
||||
int minVelocity = 0, int maxVelocity = 400, int minTrajectoryAngle = 77) :
|
||||
CParticle(position), initialPos(position), nextSmokeTicks(0), age(0),
|
||||
height(0.f)
|
||||
{
|
||||
|
@ -52,18 +53,20 @@ CChunkParticle::CChunkParticle(CPosition position, Animation *smokeAnimation) :
|
|||
direction.x = cos(radians);
|
||||
direction.y = sin(radians);
|
||||
|
||||
const int maxVelocity = 400;
|
||||
initialVelocity = MyRand() % maxVelocity;
|
||||
this->minVelocity = minVelocity;
|
||||
this->maxVelocity = maxVelocity;
|
||||
this->minTrajectoryAngle = minTrajectoryAngle;
|
||||
this->initialVelocity = this->minVelocity + MyRand() % (this->maxVelocity - this->minVelocity + 1);
|
||||
this->trajectoryAngle = deg2rad(MyRand() % (90 - this->minTrajectoryAngle) + this->minTrajectoryAngle);
|
||||
this->lifetime = (int)(1000 * (initialVelocity * sin(trajectoryAngle) / gravity) * 2);
|
||||
|
||||
int minTrajectoryAngle = 77;
|
||||
trajectoryAngle = deg2rad(MyRand() % (90 - minTrajectoryAngle) + minTrajectoryAngle);
|
||||
|
||||
lifetime = (int)(1000 * (initialVelocity * sin(trajectoryAngle) / gravity) * 2);
|
||||
this->smokeAnimation = smokeAnimation->clone();
|
||||
this->debrisAnimation = debrisAnimation->clone();
|
||||
}
|
||||
|
||||
CChunkParticle::~CChunkParticle()
|
||||
{
|
||||
delete debrisAnimation;
|
||||
delete smokeAnimation;
|
||||
}
|
||||
|
||||
|
@ -75,10 +78,8 @@ static float calculateScreenPos(float posy, float height)
|
|||
void CChunkParticle::draw()
|
||||
{
|
||||
CPosition screenPos = ParticleManager.getScreenPos(pos);
|
||||
Uint32 color = ColorBlack;
|
||||
|
||||
Video.DrawRectangleClip(color, (int)screenPos.x - 1,
|
||||
(int)calculateScreenPos(screenPos.y, height) - 1, 2, 2);
|
||||
screenPos.y = calculateScreenPos(screenPos.y, height);
|
||||
debrisAnimation->draw(static_cast<int>(screenPos.x), static_cast<int>(screenPos.y));
|
||||
}
|
||||
|
||||
static float getHorizontalPosition(int initialVelocity, float trajectoryAngle, float time)
|
||||
|
@ -105,13 +106,20 @@ void CChunkParticle::update(int ticks)
|
|||
|
||||
if (age > nextSmokeTicks) {
|
||||
CPosition p(pos.x, calculateScreenPos(pos.y, height));
|
||||
Animation *animation = smokeAnimation->clone();
|
||||
CSmokeParticle *smoke = new CSmokeParticle(p, animation);
|
||||
Animation *smokeanimation = smokeAnimation->clone();
|
||||
CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation);
|
||||
ParticleManager.add(smoke);
|
||||
|
||||
nextSmokeTicks += MyRand() % randSmokeTicks + minSmokeTicks;
|
||||
}
|
||||
|
||||
debrisAnimation->update(ticks);
|
||||
if (debrisAnimation->isFinished()) {
|
||||
Animation *debrisanimation = debrisAnimation->clone();
|
||||
delete debrisAnimation;
|
||||
debrisAnimation = debrisanimation;
|
||||
}
|
||||
|
||||
float time = age / 1000.f;
|
||||
|
||||
float distance = getHorizontalPosition(initialVelocity, trajectoryAngle, time);
|
||||
|
@ -124,7 +132,7 @@ void CChunkParticle::update(int ticks)
|
|||
|
||||
CParticle *CChunkParticle::clone()
|
||||
{
|
||||
return new CChunkParticle(pos, smokeAnimation);
|
||||
return new CChunkParticle(pos, smokeAnimation, debrisAnimation, minVelocity, maxVelocity, minTrajectoryAngle);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
78
src/particle/radialparticle.cpp
Normal file
78
src/particle/radialparticle.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name radialparticle.cpp - The radial particle. */
|
||||
//
|
||||
// (c) Copyright 2012 by cybermind
|
||||
//
|
||||
// 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
|
||||
// the Free Software Foundation; only version 2 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "particle.h"
|
||||
|
||||
CRadialParticle::CRadialParticle(CPosition position, Animation *animation, int maxSpeed) :
|
||||
CParticle(position)
|
||||
{
|
||||
Assert(animation);
|
||||
this->animation = animation->clone();
|
||||
|
||||
const int speedReduction = 10;
|
||||
|
||||
this->direction = (float)(MyRand() % 360);
|
||||
this->speed = (MyRand() % maxSpeed) / speedReduction;
|
||||
this->maxSpeed = maxSpeed;
|
||||
}
|
||||
|
||||
CRadialParticle::~CRadialParticle()
|
||||
{
|
||||
delete animation;
|
||||
}
|
||||
|
||||
void CRadialParticle::draw()
|
||||
{
|
||||
CPosition screenPos = ParticleManager.getScreenPos(pos);
|
||||
animation->draw(static_cast<int>(screenPos.x), static_cast<int>(screenPos.y));
|
||||
}
|
||||
|
||||
void CRadialParticle::update(int ticks)
|
||||
{
|
||||
this->pos.x += this->speed * sin(this->direction);
|
||||
this->pos.y += this->speed * cos(this->direction);
|
||||
|
||||
animation->update(ticks);
|
||||
if (animation->isFinished()) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
CParticle *CRadialParticle::clone()
|
||||
{
|
||||
CParticle *p = new CRadialParticle(pos, animation, maxSpeed);
|
||||
return p;
|
||||
}
|
||||
|
||||
//@}
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "iolib.h"
|
||||
|
||||
#include "iocompat.h"
|
||||
#include "map.h"
|
||||
#include "util.h"
|
||||
|
@ -48,6 +46,8 @@
|
|||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "iolib.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -512,6 +512,27 @@ void CPlayer::Save(CFile &file) const
|
|||
file.printf("\n \"total-razings\", %d,", p.TotalRazings);
|
||||
file.printf("\n \"total-kills\", %d,", p.TotalKills);
|
||||
|
||||
file.printf("\n \"speed-resource-harvest\", {");
|
||||
for (int j = 0; j < MaxCosts; ++j) {
|
||||
if (j) {
|
||||
file.printf(" ");
|
||||
}
|
||||
file.printf("%d,", p.SpeedResourcesHarvest[j]);
|
||||
}
|
||||
file.printf("},");
|
||||
file.printf("\n \"speed-resource-return\", {");
|
||||
for (int j = 0; j < MaxCosts; ++j) {
|
||||
if (j) {
|
||||
file.printf(" ");
|
||||
}
|
||||
file.printf("%d,", p.SpeedResourcesReturn[j]);
|
||||
}
|
||||
file.printf("},");
|
||||
file.printf("\n \"speed-build\", %d,", p.SpeedBuild);
|
||||
file.printf("\n \"speed-train\", %d,", p.SpeedTrain);
|
||||
file.printf("\n \"speed-upgrade\", %d,", p.SpeedUpgrade);
|
||||
file.printf("\n \"speed-research\", %d,", p.SpeedResearch);
|
||||
|
||||
Uint8 r, g, b;
|
||||
|
||||
SDL_GetRGB(p.Color, TheScreen->format, &r, &g, &b);
|
||||
|
@ -739,6 +760,14 @@ void CPlayer::Clear()
|
|||
TotalKills = 0;
|
||||
Color = 0;
|
||||
UpgradeTimers.Clear();
|
||||
for (int i = 0; i < MaxCosts; ++i) {
|
||||
SpeedResourcesHarvest[i] = SPEEDUP_FACTOR;
|
||||
SpeedResourcesReturn[i] = SPEEDUP_FACTOR;
|
||||
}
|
||||
SpeedBuild = SPEEDUP_FACTOR;
|
||||
SpeedTrain = SPEEDUP_FACTOR;
|
||||
SpeedUpgrade = SPEEDUP_FACTOR;
|
||||
SpeedResearch = SPEEDUP_FACTOR;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -303,6 +303,40 @@ void CPlayer::Load(lua_State *l)
|
|||
this->TotalResources[k] = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
} else if (!strcmp(value, "speed-resource-harvest")) {
|
||||
if (!lua_istable(l, j + 1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
const int subargs = lua_rawlen(l, j + 1);
|
||||
if (subargs != MaxCosts) {
|
||||
LuaError(l, "Wrong number of speed-resource-harvest: %d" _C_ subargs);
|
||||
}
|
||||
for (int k = 0; k < subargs; ++k) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
this->SpeedResourcesHarvest[k] = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
} else if (!strcmp(value, "speed-resource-return")) {
|
||||
if (!lua_istable(l, j + 1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
const int subargs = lua_rawlen(l, j + 1);
|
||||
if (subargs != MaxCosts) {
|
||||
LuaError(l, "Wrong number of speed-resource-harvest: %d" _C_ subargs);
|
||||
}
|
||||
for (int k = 0; k < subargs; ++k) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
this->SpeedResourcesReturn[k] = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
} else if (!strcmp(value, "speed-build")) {
|
||||
this->SpeedBuild = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "speed-train")) {
|
||||
this->SpeedTrain = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "speed-upgrade")) {
|
||||
this->SpeedUpgrade = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "speed-research")) {
|
||||
this->SpeedResearch = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "color")) {
|
||||
if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 3) {
|
||||
LuaError(l, "incorrect argument");
|
||||
|
@ -785,6 +819,32 @@ static int CclGetPlayerData(lua_State *l)
|
|||
} else if (!strcmp(data, "TotalKills")) {
|
||||
lua_pushnumber(l, p->TotalKills);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedResourcesHarvest")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const std::string res = LuaToString(l, 3);
|
||||
const int resId = GetResourceIdByName(l, res.c_str());
|
||||
lua_pushnumber(l, p->SpeedResourcesHarvest[resId]);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedResourcesReturn")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const std::string res = LuaToString(l, 3);
|
||||
const int resId = GetResourceIdByName(l, res.c_str());
|
||||
lua_pushnumber(l, p->SpeedResourcesReturn[resId]);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedBuild")) {
|
||||
lua_pushnumber(l, p->SpeedBuild);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedTrain")) {
|
||||
lua_pushnumber(l, p->SpeedTrain);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedUpgrade")) {
|
||||
lua_pushnumber(l, p->SpeedUpgrade);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "SpeedResearch")) {
|
||||
lua_pushnumber(l, p->SpeedResearch);
|
||||
return 1;
|
||||
} else {
|
||||
LuaError(l, "Invalid field: %s" _C_ data);
|
||||
}
|
||||
|
@ -858,7 +918,7 @@ static int CclSetPlayerData(lua_State *l)
|
|||
} else if (!strcmp(data, "TotalBuildings")) {
|
||||
p->TotalBuildings = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "TotalResources")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
LuaCheckArgs(l, 4);
|
||||
|
||||
const std::string res = LuaToString(l, 3);
|
||||
const int resId = GetResourceIdByName(l, res.c_str());
|
||||
|
@ -867,6 +927,26 @@ static int CclSetPlayerData(lua_State *l)
|
|||
p->TotalRazings = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "TotalKills")) {
|
||||
p->TotalKills = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "SpeedResourcesHarvest")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const std::string res = LuaToString(l, 3);
|
||||
const int resId = GetResourceIdByName(l, res.c_str());
|
||||
p->SpeedResourcesHarvest[resId] = LuaToNumber(l, 4);
|
||||
} else if (!strcmp(data, "SpeedResourcesReturn")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
|
||||
const std::string res = LuaToString(l, 3);
|
||||
const int resId = GetResourceIdByName(l, res.c_str());
|
||||
p->SpeedResourcesReturn[resId] = LuaToNumber(l, 4);
|
||||
} else if (!strcmp(data, "SpeedBuild")) {
|
||||
p->SpeedBuild = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "SpeedTrain")) {
|
||||
p->SpeedTrain = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "SpeedUpgrade")) {
|
||||
p->SpeedTrain = LuaToNumber(l, 3);
|
||||
} else if (!strcmp(data, "SpeedResearch")) {
|
||||
p->SpeedResearch = LuaToNumber(l, 3);
|
||||
} else {
|
||||
LuaError(l, "Invalid field: %s" _C_ data);
|
||||
}
|
||||
|
|
|
@ -281,17 +281,6 @@ std::string CliMapName; /// Filename of the map given on the command li
|
|||
static std::vector<gcn::Container *> Containers;
|
||||
std::string MenuRace;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Speedups FIXME: Move to some other more logic place
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
int SpeedResourcesHarvest[MaxCosts]; /// speed factor for harvesting resources
|
||||
int SpeedResourcesReturn[MaxCosts]; /// speed factor for returning resources
|
||||
int SpeedBuild = 1; /// speed factor for building
|
||||
int SpeedTrain = 1; /// speed factor for training
|
||||
int SpeedUpgrade = 1; /// speed factor for upgrading
|
||||
int SpeedResearch = 1; /// speed factor for researching
|
||||
|
||||
/*============================================================================
|
||||
== DISPLAY
|
||||
============================================================================*/
|
||||
|
|
|
@ -27,11 +27,19 @@ public:
|
|||
class CChunkParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CChunkParticle(CPosition position, Animation *smokeAnimation);
|
||||
CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation, int minVelocity = 0, int maxVelocity = 400, int minTrajectoryAngle = 77);
|
||||
};
|
||||
|
||||
class CSmokeParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CSmokeParticle(CPosition position, Animation *animation);
|
||||
};
|
||||
|
||||
class CRadialParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CRadialParticle(CPosition position, Animation *smokeAnimation, int maxSpeed);
|
||||
};
|
||||
|
||||
class CParticleManager
|
||||
|
|
|
@ -43,6 +43,13 @@ class CPlayer
|
|||
int TotalRazings;
|
||||
int TotalKills;
|
||||
|
||||
int SpeedResourcesHarvest[MaxCosts];
|
||||
int SpeedResourcesReturn[MaxCosts];
|
||||
int SpeedBuild;
|
||||
int SpeedTrain;
|
||||
int SpeedUpgrade;
|
||||
int SpeedResearch;
|
||||
|
||||
CUnit& GetUnit(int index) const;
|
||||
int GetUnitCount() const;
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ static void DoRightButton_Attack(CUnit &unit, CUnit *dest, const Vec2i &pos, int
|
|||
const int action = type.MouseAction;
|
||||
|
||||
if (dest != NULL && unit.CurrentAction() != UnitActionBuilt) {
|
||||
if (unit.IsEnemy(*dest)) {
|
||||
if (action == MouseActionSpellCast || unit.IsEnemy(*dest)) {
|
||||
dest->Blink = 4;
|
||||
if (!acknowledged) {
|
||||
PlayUnitSound(unit, VoiceAttack);
|
||||
|
|
|
@ -990,6 +990,31 @@ static int CclGetUnits(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
**
|
||||
** Get the value of the unit bool-flag.
|
||||
**
|
||||
** @param l Lua state.
|
||||
**
|
||||
** @return The value of the bool-flag of the unit.
|
||||
*/
|
||||
static int CclGetUnitBoolFlag(lua_State *l)
|
||||
{
|
||||
LuaCheckArgs(l, 2);
|
||||
|
||||
lua_pushvalue(l, 1);
|
||||
const CUnit *unit = CclGetUnit(l);
|
||||
lua_pop(l, 1);
|
||||
|
||||
const char *const value = LuaToString(l, 2);
|
||||
int index = UnitTypeVar.BoolFlagNameLookup[value];// User bool flags
|
||||
if (index == -1) {
|
||||
LuaError(l, "Bad bool-flag name '%s'\n" _C_ value);
|
||||
}
|
||||
lua_pushboolean(l, unit->Type->BoolFlag[index].value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Get the value of the unit variable.
|
||||
**
|
||||
|
@ -1130,6 +1155,7 @@ void UnitCclRegister()
|
|||
lua_register(Lua, "GetUnits", CclGetUnits);
|
||||
|
||||
// unit member access functions
|
||||
lua_register(Lua, "GetUnitBoolFlag", CclGetUnitBoolFlag);
|
||||
lua_register(Lua, "GetUnitVariable", CclGetUnitVariable);
|
||||
lua_register(Lua, "SetUnitVariable", CclSetUnitVariable);
|
||||
|
||||
|
|
|
@ -639,6 +639,31 @@ static int CclDefineUnitType(lua_State *l)
|
|||
} else {
|
||||
LuaError(l, "Unsupported Type: %s" _C_ value);
|
||||
}
|
||||
} else if (!strcmp(value, "MissileOffsets")) {
|
||||
if (!lua_istable(l, -1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
const int subargs = lua_rawlen(l, -1);
|
||||
for (int k = 0; k < subargs; ++k) {
|
||||
lua_rawgeti(l, -1, k + 1);
|
||||
if (!lua_istable(l, -1) || lua_rawlen(l, -1) != UnitSides) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
for (int m = 0; m < UnitSides; ++m) {
|
||||
lua_rawgeti(l, -1, m + 1);
|
||||
if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
lua_rawgeti(l, -1, 1);
|
||||
type->MissileOffsets[m][k].x = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
lua_rawgeti(l, -1, 2);
|
||||
type->MissileOffsets[m][k].y = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
} else if (!strcmp(value, "Impact")) {
|
||||
if (!lua_istable(l, -1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
|
|
|
@ -477,7 +477,7 @@ void CUnit::Init()
|
|||
void CUnit::Release(bool final)
|
||||
{
|
||||
if (Type == NULL) {
|
||||
DebugPrint("unit already free");
|
||||
DebugPrint("unit already free\n");
|
||||
return;
|
||||
}
|
||||
Assert(Orders.size() == 1);
|
||||
|
@ -492,6 +492,9 @@ void CUnit::Release(bool final)
|
|||
Destroyed = 1; // mark as destroyed
|
||||
|
||||
if (Container && !final) {
|
||||
if (Boarded) {
|
||||
Container->BoardCount--;
|
||||
}
|
||||
MapUnmarkUnitSight(*this);
|
||||
RemoveUnitFromContainer(*this);
|
||||
}
|
||||
|
@ -2938,10 +2941,7 @@ int CanTransport(const CUnit &transporter, const CUnit &unit)
|
|||
if (transporter.BoardCount >= transporter.Type->MaxOnBoard) { // full
|
||||
return 0;
|
||||
}
|
||||
// FIXME: remove UnitTypeLand requirement
|
||||
if (unit.Type->UnitType != UnitTypeLand) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Can transport only allied unit.
|
||||
// FIXME : should be parametrable.
|
||||
if (!transporter.IsTeamed(unit)) {
|
||||
|
|
|
@ -165,6 +165,7 @@ CUnitType::CUnitType() :
|
|||
memset(ResInfo, 0, sizeof(ResInfo));
|
||||
memset(&NeutralMinimapColorRGB, 0, sizeof(NeutralMinimapColorRGB));
|
||||
memset(ImproveIncomes, 0, sizeof(ImproveIncomes));
|
||||
memset(MissileOffsets, 0, sizeof(MissileOffsets));
|
||||
}
|
||||
|
||||
CUnitType::~CUnitType()
|
||||
|
|
|
@ -252,6 +252,8 @@ static int CclDefineModifier(lua_State *l)
|
|||
memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades));
|
||||
memset(um->ApplyTo, '?', sizeof(um->ApplyTo));
|
||||
um->Modifier.Variables = new CVariable[UnitTypeVar.GetNumberVariable()];
|
||||
um->ModifyPercent = new int[UnitTypeVar.GetNumberVariable()];
|
||||
memset(um->ModifyPercent, 0, UnitTypeVar.GetNumberVariable() * sizeof(int));
|
||||
|
||||
um->UpgradeId = UpgradeIdByIdent(LuaToString(l, 1));
|
||||
|
||||
|
@ -338,17 +340,28 @@ static int CclDefineModifier(lua_State *l)
|
|||
} else {
|
||||
int index = UnitTypeVar.VariableNameLookup[key]; // variable index;
|
||||
if (index != -1) {
|
||||
lua_rawgeti(l, j + 1, 2);
|
||||
if (lua_istable(l, -1)) {
|
||||
DefineVariableField(l, um->Modifier.Variables + index, -1);
|
||||
} else if (lua_isnumber(l, -1)) {
|
||||
um->Modifier.Variables[index].Enable = 1;
|
||||
um->Modifier.Variables[index].Value = LuaToNumber(l, -1);
|
||||
um->Modifier.Variables[index].Max = LuaToNumber(l, -1);
|
||||
if (lua_rawlen(l, j + 1) == 3) {
|
||||
lua_rawgeti(l, j + 1, 3);
|
||||
const char *value = LuaToString(l, -1);
|
||||
lua_pop(l, 1);
|
||||
if (!strcmp(value, "Percent")) {
|
||||
lua_rawgeti(l, j + 1, 2);
|
||||
um->ModifyPercent[index] = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
} else {
|
||||
LuaError(l, "bad argument type for '%s'\n" _C_ key);
|
||||
lua_rawgeti(l, j + 1, 2);
|
||||
if (lua_istable(l, -1)) {
|
||||
DefineVariableField(l, um->Modifier.Variables + index, -1);
|
||||
} else if (lua_isnumber(l, -1)) {
|
||||
um->Modifier.Variables[index].Enable = 1;
|
||||
um->Modifier.Variables[index].Value = LuaToNumber(l, -1);
|
||||
um->Modifier.Variables[index].Max = LuaToNumber(l, -1);
|
||||
} else {
|
||||
LuaError(l, "bad argument type for '%s'\n" _C_ key);
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
} else {
|
||||
LuaError(l, "wrong tag: %s" _C_ key);
|
||||
}
|
||||
|
@ -583,19 +596,28 @@ static void ApplyUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
|
|||
for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
|
||||
varModified |= um->Modifier.Variables[j].Value
|
||||
| um->Modifier.Variables[j].Max
|
||||
| um->Modifier.Variables[j].Increase;
|
||||
stat.Variables[j].Value += um->Modifier.Variables[j].Value;
|
||||
| um->Modifier.Variables[j].Increase
|
||||
| um->Modifier.Variables[j].Enable
|
||||
| um->ModifyPercent[j];
|
||||
stat.Variables[j].Enable = um->Modifier.Variables[j].Enable;
|
||||
if (um->ModifyPercent[j]) {
|
||||
stat.Variables[j].Value += stat.Variables[j].Value * um->ModifyPercent[j] / 100;
|
||||
stat.Variables[j].Max += stat.Variables[j].Max * um->ModifyPercent[j] / 100;
|
||||
} else {
|
||||
stat.Variables[j].Value += um->Modifier.Variables[j].Value;
|
||||
stat.Variables[j].Max += um->Modifier.Variables[j].Max;
|
||||
stat.Variables[j].Increase += um->Modifier.Variables[j].Increase;
|
||||
}
|
||||
|
||||
if (stat.Variables[j].Value < 0) {
|
||||
stat.Variables[j].Value = 0;
|
||||
}
|
||||
stat.Variables[j].Max += um->Modifier.Variables[j].Max;
|
||||
if (stat.Variables[j].Max < 0) {
|
||||
stat.Variables[j].Max = 0;
|
||||
}
|
||||
if (stat.Variables[j].Value > stat.Variables[j].Max) {
|
||||
stat.Variables[j].Value = stat.Variables[j].Max;
|
||||
}
|
||||
stat.Variables[j].Increase += um->Modifier.Variables[j].Increase;
|
||||
}
|
||||
|
||||
// And now modify ingame units
|
||||
|
@ -610,7 +632,15 @@ static void ApplyUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
|
|||
continue;
|
||||
}
|
||||
for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
|
||||
unit.Variable[j].Value += um->Modifier.Variables[j].Value;
|
||||
unit.Variable[j].Enable = um->Modifier.Variables[j].Enable;
|
||||
if (um->ModifyPercent[j]) {
|
||||
unit.Variable[j].Value += unit.Variable[j].Value * um->ModifyPercent[j] / 100;
|
||||
unit.Variable[j].Max += unit.Variable[j].Max * um->ModifyPercent[j] / 100;
|
||||
} else {
|
||||
unit.Variable[j].Value += um->Modifier.Variables[j].Value;
|
||||
unit.Variable[j].Increase += um->Modifier.Variables[j].Increase;
|
||||
}
|
||||
|
||||
if (unit.Variable[j].Value < 0) {
|
||||
unit.Variable[j].Value = 0;
|
||||
}
|
||||
|
@ -621,7 +651,6 @@ static void ApplyUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
|
|||
if (unit.Variable[j].Value > unit.Variable[j].Max) {
|
||||
unit.Variable[j].Value = unit.Variable[j].Max;
|
||||
}
|
||||
unit.Variable[j].Increase += um->Modifier.Variables[j].Increase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue