Merge branch 'Wargus:master' into master
This commit is contained in:
commit
75d523d819
27 changed files with 544 additions and 87 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,7 @@
|
|||
.cache
|
||||
debian/tmp/*
|
||||
gmon.*
|
||||
valgrind.*
|
||||
debian/*.debhelper
|
||||
debian/*.log
|
||||
debian/*.substvars
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
# Stratagus major version
|
||||
set(STRATAGUS_MAJOR_VERSION 3)
|
||||
# Stratagus minor version (maximum 99)
|
||||
set(STRATAGUS_MINOR_VERSION 2)
|
||||
set(STRATAGUS_MINOR_VERSION 3)
|
||||
# Stratagus patch level (maximum 99)
|
||||
set(STRATAGUS_PATCH_LEVEL 1)
|
||||
# Stratagus patch level 2
|
||||
|
|
332
debian/changelog
vendored
332
debian/changelog
vendored
|
@ -1,8 +1,334 @@
|
|||
stratagus (3.2.1) UNRELEASED; urgency=medium
|
||||
stratagus (3.3.1) UNRELEASED; urgency=medium
|
||||
|
||||
*
|
||||
[ Tim Felgentreff ]
|
||||
* fix potential crash in editor with dynamic load
|
||||
* ony draw references on units with debug print
|
||||
* fix wrong assert, compilation on ubuntu 22.04
|
||||
|
||||
-- Tim Felgentreff <timfelgentreff@gmail.com> Sat, 25 Dec 2021 06:45:52 +0100
|
||||
[ Northfear ]
|
||||
* Fix build with enabled DYNAMIC_LOAD
|
||||
|
||||
-- Tim Felgentreff <timfelgentreff@gmail.com> Sat, 30 Jul 2022 13:22:22 +0200
|
||||
|
||||
stratagus (3.3.0) focal; urgency=medium
|
||||
|
||||
[ Alex Grant Benedict ]
|
||||
* Update stratagus-tinyfiledialogs.h
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* On windows, prefer stratagus from PATH over registry
|
||||
|
||||
[ Alyokhin ]
|
||||
* Fixed fog for non-square maps
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* workaround a few crashes in the online service
|
||||
* add password flag to text fields
|
||||
* HACK: make ctrl+keys work again in guichan
|
||||
* add a lua function to restart the game
|
||||
* guard against potential crashes due to bad lua coding of menus
|
||||
* allow immediate reconnect to online service
|
||||
* guard against lost network callbacks
|
||||
* return success/failure from LoadStratagusMapInfo
|
||||
* compile with c++17 filesystem support
|
||||
* implement transmitting maps from server to client during join
|
||||
* fix idle crash when online
|
||||
* expose full file path in __file__; add disabled filesystem listing lua function
|
||||
* allow unit selection in editor
|
||||
* use ChangeOwner in SetUnitVariable(..."Player")
|
||||
* add ability to change unit color in SetUnitVariable
|
||||
* editor fixes
|
||||
* add CopyUnitType function
|
||||
* fix SetUnitVariable("Color")
|
||||
* add GiveUnitsToPlayer function
|
||||
* use lookup tables for cp437 and cp866 font graphics
|
||||
* add support for mapping between codepages
|
||||
|
||||
[ Simone Starace ]
|
||||
* Changed the body of function ChangeUnitsOwner.
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* better docs for SetFontCodePage
|
||||
* avoid useless utf8 work for numbers
|
||||
* update codepoint mapping to allow multichar subst
|
||||
* rename mobdebug.h, not a real header
|
||||
* allow setting NumBounces for missile-clip-to-target
|
||||
* draw missile cliptotarget centered on top left corner of target
|
||||
* add animated sprite decoration
|
||||
* add button check units-nor and fix CopyUnitType
|
||||
* fix walls disappearing when changing surroundings
|
||||
* use sdl hardware cursor to decouple the cursor speed from the game speed
|
||||
* fix cursor drawing, now only the offset may be wrong
|
||||
* fix mouse event coordinates for vertical pixel stretching
|
||||
* make hardware cursor a preference
|
||||
* fix scaled cursor hot pos
|
||||
* deselect for list boxes
|
||||
* try to clean up a bit better
|
||||
* allow using bool flags for enable/disable decoration
|
||||
* a bit more configurability for the decoration bar
|
||||
* fix one more potential crash with font rendering
|
||||
* add option to indicate damage in selection rect
|
||||
* only show group if ShowOrders is true
|
||||
* Make max messages configurable with SetMaxMessageCount and rework repeated message handling
|
||||
* add a simple function to copy unit buttons to another unit
|
||||
* add ability to set completely custom Colors for a unit
|
||||
* add ability to define additional colors and set custom unit color
|
||||
* fix a class of potential NPEs
|
||||
* fix a crash in select script functions
|
||||
* first attempt at a "randomizer" tool for the editor
|
||||
* fix memory leak, thanks @Andrettin
|
||||
* improve astar cleanup performance. thanks @Andrettin
|
||||
* don't return depots unconditionally
|
||||
* fix start location sticking to cursor
|
||||
* tweak map randomize
|
||||
* be backwards compatible with war1gus colorsets
|
||||
* make randomize editor feature configurable
|
||||
* add import
|
||||
* expose Randomize map to lua
|
||||
* Revert "improve astar cleanup performance. thanks @Andrettin"
|
||||
* Revert "don't return depots unconditionally"
|
||||
* tweak map randomization
|
||||
* fix two potential crashes
|
||||
* Revert "Revert "don't return depots unconditionally""
|
||||
* Revert "Revert "improve astar cleanup performance. thanks @Andrettin""
|
||||
* better random for random maps
|
||||
* Add FindNextResource lua function
|
||||
* make free workers icon clickable and hideable when no free workers available
|
||||
* pause game when network is out of sync
|
||||
* improve UnitDump logging
|
||||
* improve logging of network out of sync
|
||||
* SyncHash change logging
|
||||
* ask for port for easy multiplayer debugging
|
||||
* reduce backtrace size
|
||||
* dump unit debug in dev launch
|
||||
* more debugging and sync hashing
|
||||
* sort the CUnit::Init variables as in the header
|
||||
* workaround for not finding depot from mine
|
||||
* port depot finder change from Wyrmgus that searches from outside mine
|
||||
* add disabled astar overlay
|
||||
* disable a bit of the extra much logging again
|
||||
|
||||
[ sviscapi ]
|
||||
* Changed boolean into bool in online_service.cpp
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* reuse game structures in replay types
|
||||
* delete metaserver
|
||||
* WIP: start unifying all GameSettings
|
||||
* doc update for SetPlayerData
|
||||
* fix SettingsPresets#Init
|
||||
* more room for backtrace
|
||||
* fix replay refactpring
|
||||
* fix team assignments again
|
||||
* fix build issues on linux
|
||||
* don't use enum class until we remove tolua++
|
||||
* always use vendored lua
|
||||
* cleanups
|
||||
* make changes work with tolua++, trying to be backwards compatible
|
||||
* since FoV is relevant for sync, make it part of GameSettings
|
||||
* move sync-relevant preferences into GameSettings
|
||||
* debugprint game settings, fix sign of some settings
|
||||
* give games the opportunity to store custom settings in GameSettings that get synced across the network
|
||||
* ensure we store team preferences in replay and always re-init GameSettings with user preferences where applicable
|
||||
* Revert "always use vendored lua"
|
||||
* AiChecksDependencies is now synced across network clients
|
||||
* don't autosave during replay
|
||||
* always use network command queue, even in single player, for replays to work
|
||||
* fix wrong assert
|
||||
* fixed another assert problem when game is cleaning up
|
||||
|
||||
[ alyokhin ]
|
||||
* fix compile error for gcc version >9.3.0
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* dirty expansion to multiplayer random placement option
|
||||
* fix server setup message size
|
||||
* new idea for player order pref
|
||||
* simplify network code
|
||||
* ignore linux build
|
||||
* fix game start, also serialize presets in server state
|
||||
* fix wrong bounds for network commands after refactoring
|
||||
* debug: try building with v142 toolset
|
||||
* drop XP support from settings file
|
||||
* show it as training when building from outside
|
||||
* fix diagonal rule checks for buildings
|
||||
* cancel building when building from outside and stopping
|
||||
* make sure we cannot build nonsolid decorative buildings on water
|
||||
* compact host array before game start
|
||||
* send the new client index out to clients after compacting host array
|
||||
* allow grayscale graphic loading
|
||||
* debug print replay settings
|
||||
* fix and document player team assignement via presets
|
||||
* use references instead of copy of hosts
|
||||
* avoid vectors as public static global members
|
||||
* expose the boolean flags that moved to GameSettings
|
||||
* set shared vision for teamed players
|
||||
* newline in lua DebugPrint
|
||||
* make SaveReplay work again
|
||||
* minimum fix for "static initializer fiasco"
|
||||
* don't reset NumDirections and Flip
|
||||
* use std::bitset for user settings manipulation
|
||||
* more flexibile default tile index
|
||||
* implement terrain harvesting of other resources than wood.
|
||||
* add "non-mixing" flag for solid tiles that don't need mixing
|
||||
* ignore building rules when not in game (i.e. editor)
|
||||
* don't count more than 10 repeats of a message
|
||||
* fix checking of resource for terrain resources
|
||||
* show buttons from *the* neutral player 16
|
||||
* push clicking player into button callback action
|
||||
* allow terrain harvesters to return resources early
|
||||
* fix outside builder for buildings
|
||||
* make popups accept functions
|
||||
* allow plain graphic as panel content
|
||||
* 1-based player index for users
|
||||
* add option for ellipse selection with y-stretch factor
|
||||
* fix compiler warning
|
||||
* make color cycling speed configurable
|
||||
* make scroll margins configurable
|
||||
* fix editor ui bug with 5x5 cursor
|
||||
* fix transports getting stuck during unloading. fixes https://github.com/Wargus/wargus/issues/121
|
||||
* simplify upgrade_to check, give back resources when upgrade fails. fixes https://github.com/Wargus/wargus/issues/172
|
||||
* play shore sound only when really docking/undocking
|
||||
* minor fix for transporter pathing
|
||||
* use an external command to play midi music on windows
|
||||
* exe name fix
|
||||
* ship midiplayer to clients
|
||||
* minor cleanup for movie playing
|
||||
* let midiplayer work with non-standard windows midi
|
||||
* fix linux build
|
||||
* add some more flexibility for live reloading of ui, allow using frames in panel graphics
|
||||
* fix negative condition for panel content on variable value
|
||||
* fix a crash
|
||||
* add a wiggle animation for ships and planes to have sub-tile movement
|
||||
* fixup last commit
|
||||
* Expose unit variables PosBottom and PosRight
|
||||
* allow rotating towards building unit, take displacement into account
|
||||
* implement displacement move towards a unit
|
||||
* use GetDrawLevel() for map drawing order calculation
|
||||
* fix potential crash when portraits are used, draw portrait of first selected unit in group
|
||||
* add support for different icons drawn based on health for single, multi, and transport selection
|
||||
* allow content type icon to select icon kind (group, single, button, transport)
|
||||
* fix mng constructor
|
||||
* add "talking" as a tag in portrait definitions to show when unit is playing sound
|
||||
* add support for UI.DefaultUnitPortrait to draw when no selection is active
|
||||
* do not randomly play talking animations
|
||||
|
||||
[ Simone Starace ]
|
||||
* Bold text on some examples.
|
||||
* Added examples in shaders.cpp
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* use 32-bit alpha for fancy shadows
|
||||
|
||||
[ Simone Starace ]
|
||||
* Added more example codes for units scripts.
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* new code for palette changes in icons based on unit variables
|
||||
* support alternative spritesheet for units below 50% health
|
||||
* add a simple mechanism to combine graphics from lua with overlay/mask
|
||||
* apply a shearing effect to generated shadows
|
||||
* add shrinking for shadows
|
||||
* clean up MakeShadow function a bit
|
||||
* download/setup stargus
|
||||
* support size in SDL_RWops from CFile
|
||||
* share mngs
|
||||
* let sdl mixer free our sdl_rwops
|
||||
* allow dynamic load of sounds as well
|
||||
* make dynamic load the default to start up faster
|
||||
* don't overallocate mng array
|
||||
* deal with a few minor errors
|
||||
* make construction lazy loaded as well
|
||||
* fix lazy loading of mng portraits
|
||||
* keep units in transports sorted by size and give them space in UI
|
||||
* fix ordering of units in transports by size
|
||||
* extract arg quoting for iwndows
|
||||
* make midiplayer more fancy with pipes for communication
|
||||
* add missing stargus json
|
||||
* download magick executable
|
||||
* fix icon color palette swaps not being swapped back to default
|
||||
* add assertions to avoid crash with wrongly indexed graphics
|
||||
* update generate_index script to create api definition
|
||||
* add a todo
|
||||
* fix potential crash
|
||||
* fix wrong assert
|
||||
* fix missing semicolon
|
||||
* make generated api better
|
||||
* cache mapping of strings to filenames
|
||||
* avoid runtime conversion to SDL_Color for font colors
|
||||
* cache SDL colors for player colors at beginning of the game
|
||||
* add simple benchmarking option
|
||||
* fix a crash when freeing dynamically loaded sounds
|
||||
* nicer fps bar
|
||||
* set callback immediately when playing, not delayed
|
||||
* port Wyrmgus change to FormatNumber, which has better performance
|
||||
* fix a bunch of clang warnings
|
||||
* make compilation without openmp work
|
||||
* also build shared libraries of vendored lua
|
||||
* fix omp_get_thread_num stub
|
||||
* explicit sound channel initialization
|
||||
* openmp cmake option
|
||||
* add gprof linker flag
|
||||
* make unit manager a global pointer, not a static global
|
||||
* make FogOfWar a global pointer, not a static global
|
||||
* check automatic attacks/spells fewer times to avoid performance penalty of AStar each cycle
|
||||
* make vendored lua also work on windows
|
||||
* dispatch audio callbacks to the event loop
|
||||
* fixup failing music callback - don't let music play failure spam the event queue
|
||||
* don't wait for vsync in benchmark mode
|
||||
* allocate tileset on map creation, not statically
|
||||
* fix lazy mng loading
|
||||
* hackaround for mng free bug
|
||||
* fix exit when no map was created
|
||||
* make full black in mngs be transparent
|
||||
* don't waste time drawing map tiles below fog of war
|
||||
* fix debug printing with dummy renderer
|
||||
* fix swapped mng sizes
|
||||
* fix compile error
|
||||
* fix wrong condition for mng lazy loading
|
||||
* fix invalid sharing of mngs in copied unit type
|
||||
* mng widgets are always dirty
|
||||
* fix potential crash when lazily loading a sound that doesn't exist
|
||||
* delete manually allocated UnitManager and FogOfWar
|
||||
* expose Mng.MaxFPS to lua to set the max playback speed for mngs
|
||||
* fix compilation without Mng support
|
||||
* minor usability improvement for panel conditions
|
||||
* no assert/debugprint in release builds
|
||||
* XXX: do not crash on exit
|
||||
* improve performance of AiEnemyUnitsInDistance
|
||||
* reduce load on AI cycles by limiting how many forces may scan the map in one cycle
|
||||
* change astar reset optimization to instead rely on memory alignment and the compiler optimizations for memset/memmove on aligned memory chunks with modern CPUs
|
||||
* make max iterations for astar configurable
|
||||
* comment unused cpu feature test code, align 512bits for AVX-512
|
||||
* report benchmark results with cycles
|
||||
* no assert/debugprint in release builds
|
||||
* XXX: do not crash on exit
|
||||
* re-enable simd test functions
|
||||
* re-order to fix compilation
|
||||
* start skipping frames when we are too slow
|
||||
* fix typo
|
||||
* more frame skipping, to work decently on rpi without accelleration
|
||||
* avoid free-cycle
|
||||
|
||||
[ Sebastien Alaiwan ]
|
||||
* Cleanup: dead local variables
|
||||
* genversion: fix minor memory leak
|
||||
|
||||
[ Tim Felgentreff ]
|
||||
* minor tweaks to micro-optimize performance for really slow machines
|
||||
* fix potential crash on map load
|
||||
* add workaround for potential crash on load
|
||||
* Revert "XXX: do not crash on exit"
|
||||
* Revert "no assert/debugprint in release builds"
|
||||
* make frame skip a preference
|
||||
* fix loading games with units in containers that do not have a type yet
|
||||
* move tileset allocation to the explicit list of globals allocated in stratagusMain
|
||||
* fix accidental double-free
|
||||
* (i think) fix an assertion
|
||||
* fix crash when graphic for flipped missile is loaded already as sprite
|
||||
* add a bit of documentation about complex map building
|
||||
|
||||
-- Tim Felgentreff <timfelgentreff@gmail.com> Wed, 27 Jul 2022 14:16:51 +0200
|
||||
|
||||
stratagus (3.2.0) focal; urgency=medium
|
||||
|
||||
|
|
4
debian/copyright
vendored
4
debian/copyright
vendored
|
@ -6,11 +6,11 @@ Copyright:
|
|||
© 2004 David Martínez Moreno <ender@debian.org>
|
||||
© 2010-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||
© 2015 cybermind <iddqd_mail@mail.ru>
|
||||
© 2016-2021 Tim Felgentreff <timfelgentreff@gmail.com>
|
||||
© 2016-2022 Tim Felgentreff <timfelgentreff@gmail.com>
|
||||
License: GPL-2+
|
||||
|
||||
Files: *
|
||||
© 1998-2021 by The Stratagus Project, including, among others:
|
||||
© 1998-2022 by The Stratagus Project, including, among others:
|
||||
Jimmy Salmon <jsalmon3@users.sourceforge.net>
|
||||
Russel Smith <mr-russ@users.sourceforge.net>
|
||||
Nehal Mistry <nehalmistry@users.sourceforge.net>
|
||||
|
|
137
doc/BuildingComplexMaps.md
Normal file
137
doc/BuildingComplexMaps.md
Normal file
|
@ -0,0 +1,137 @@
|
|||
# Building Complex Maps
|
||||
|
||||
The Stratagus engine is very flexible when it comes to custom maps, even though
|
||||
most of the flexibility is not exposed in the map editor. This document aims to
|
||||
provide a bit of guidance if you want to create custom missions with complex
|
||||
setups, triggers, and/or objectives.
|
||||
|
||||
## 1. Build the map in the map editor
|
||||
|
||||
#### 1.1 Create the basics
|
||||
|
||||
The first step should be to build the basic map in the map editor. This includes
|
||||
setting up how many factions you need and of which colors, their units, the
|
||||
terrain etc. Basically, anything that can be done in the editor, should be done
|
||||
in the editor
|
||||
|
||||
#### 1.2 Touch up appearances
|
||||
|
||||
The map editor comes with a feature to draw "decoration" tiles, that is, to draw
|
||||
tiles without automatically changing and adjusting the tiles around it. This
|
||||
feature is really for the last touch ups, since afterwards the tiles cannot be
|
||||
reverted to automatic updates from the UI. So, if you are sure you are done with
|
||||
the terrain, you can use this touch-up feature to draw single tiles of specific
|
||||
variant to have the maximum control over the terrain.
|
||||
|
||||
## 2. Adapt the Scripts
|
||||
|
||||
A map is saved into two files a `.smp` and a `.sms` file. You should not touch
|
||||
these files. Instead, you can create (if they do not already exist) two
|
||||
additional files to write custom lua code that can enhance the map when it is
|
||||
loaded. For example, if your map is called `my_map`, then you would have a file
|
||||
`my_map.sms` and `my_map.smp`. You can add files `my_map.sms.preamble` and
|
||||
`my_map.sms.postamble`. The first is loaded *before* the map is loaded (so you
|
||||
can, for example, change how units are created by changing the definition of the
|
||||
`CreateUnit` function). The second is loaded *after* the map, so you can add
|
||||
additional custom events and objectives. Let's talk about this latter case
|
||||
first.
|
||||
|
||||
#### 2.1 Custom events and objectives
|
||||
|
||||
In-game events and objectives are coded the same way. Open the `.sms.postamble`
|
||||
file in an editor of your choice. All objectives and events are done using
|
||||
"Triggers". Triggers are pairs of functions that are run at regular intervals by
|
||||
the game. A complex victory condition trigger can look like this:
|
||||
|
||||
```
|
||||
local victoryTimer = -1
|
||||
|
||||
AddTrigger(
|
||||
function()
|
||||
if GetNumUnitsAt(
|
||||
GetThisPlayer(), "any",
|
||||
{Map.Info.MapWidth / 2 - 5, Map.Info.MapHeight / 2 - 5},
|
||||
{Map.Info.MapWidth / 2 + 5, Map.Info.MapHeight / 2 + 5}) > 5 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end,
|
||||
function()
|
||||
AddMessage("5 Units in the center!")
|
||||
victoryTimer = 10
|
||||
return false
|
||||
end
|
||||
)
|
||||
|
||||
AddTrigger(
|
||||
function()
|
||||
if victoryTimer > 0 then
|
||||
victoryTimer = victoryTimer - 1
|
||||
AddMessage("Time remaining until victory: " .. victoryTimer)
|
||||
end
|
||||
return victoryTimer == 0
|
||||
end,
|
||||
function()
|
||||
return ActionVictory()
|
||||
end
|
||||
)
|
||||
```
|
||||
|
||||
Let's unpack this. We are defining two triggers. The first function is the
|
||||
"condition function" of the trigger. The second function is the actual
|
||||
trigger. The first function is run at regular intervals during the game until it
|
||||
returns `true`. Only then is the second function run. If the second function
|
||||
returns `false`, then that trigger will be removed and will never run again.
|
||||
|
||||
The first trigger condition here checks if the number of units of the active
|
||||
player in the map center (in a 10x10 grid around the map center) is larger
|
||||
than 5. If this is true, the condition returns true and the second function
|
||||
runs. The second function shows a message that 5 units are now at the center and
|
||||
sets the variable `victoryTimer` to 10.
|
||||
|
||||
The second trigger just keeps checking the `victoryTimer` variable. As long as
|
||||
that variable is less than 0, nothing happens. But when the first trigger has
|
||||
fired and set the variable to 10, then the second trigger will start counting it
|
||||
down and show that as an in-game message. Once the `victoryTimer` has counted
|
||||
down to 0, the condition of the second trigger returns `true` and the action
|
||||
function runs. The action function in this case just calls `ActionVictory`. What
|
||||
that means is the game ends with a victory.
|
||||
|
||||
For conditions where the game should be lost, `ActionDefeat` is used.
|
||||
|
||||
Note how powerful this can be. Of course, now we are just using a trigger to
|
||||
show some message and set a variable, but you could have triggers that spawn or
|
||||
transform units, change diplomacy, scroll the map somewhere, pause the game and
|
||||
show an "in-game dialogue", or even change tiles on the map to have something
|
||||
like a "natural disaster event" that changes the face of the earth. For all the
|
||||
things you can do, check the Lua functions that are available:
|
||||
https://stratagus.com/lua_bindings.html
|
||||
|
||||
#### 2.2 Custom alliances
|
||||
|
||||
A common request for complex games is to be able to declare custom alliances,
|
||||
like some AI players being in a team with the player or player co-op against
|
||||
AI. This can be achieved using a custom startup function.
|
||||
|
||||
After the game is loaded and everything is ready to start running, Stratagus
|
||||
calls one last Lua function to do any last minute setup. This Lua function is
|
||||
`GameStarting`.
|
||||
|
||||
As an example, you can add this to your `.sms.preamble` file:
|
||||
|
||||
```
|
||||
local OldGameStarting = GameStarting
|
||||
function GameStarting()
|
||||
OldGameStarting()
|
||||
SetDiplomacy(0, "allied", 2)
|
||||
SetSharedVision(0, true, 2)
|
||||
SetDiplomacy(2, "allied", 0)
|
||||
SetSharedVision(2, true, 0)
|
||||
GameStarting = OldGameStarting
|
||||
end
|
||||
```
|
||||
|
||||
This will ensure that at the beginning of the game, players 0 and 2 are always
|
||||
allied. Just as with triggers, all the Lua functions are available to you here,
|
||||
so anything can be done at this point.
|
|
@ -460,12 +460,12 @@ void COrder_Attack::SetAutoTarget(CUnit &unit, CUnit *target)
|
|||
**/
|
||||
bool COrder_Attack::AutoSelectTarget(CUnit &unit)
|
||||
{
|
||||
// don't check if we want to switch targets each cycle, once every second is enough
|
||||
// don't check if we want to switch targets each cycle, but not too rarely either, because then attack-move doesn't work properly anymore
|
||||
if (Sleep > 0) {
|
||||
Sleep -= 1;
|
||||
return true;
|
||||
}
|
||||
Sleep = CYCLES_PER_SECOND / 2;
|
||||
Sleep = CYCLES_PER_SECOND / 5;
|
||||
|
||||
// if unit can't attack, or if unit is not bunkered and removed - exit, no targets
|
||||
if (unit.Type->CanAttack == false
|
||||
|
|
|
@ -938,6 +938,11 @@ static void DrawStartLocations()
|
|||
const PixelPos startScreenPos = vp->TilePosToScreen_TopLeft(Players[i].StartPos);
|
||||
|
||||
if (type) {
|
||||
#ifdef DYNAMIC_LOAD
|
||||
if (!type->Sprite) {
|
||||
LoadUnitTypeSprite(*const_cast<CUnitType *>(type));
|
||||
}
|
||||
#endif
|
||||
DrawUnitType(*type, type->Sprite, i, 0, startScreenPos);
|
||||
} else { // Draw a cross
|
||||
DrawCross(startScreenPos, Map.Tileset->getPixelTileSize(), Players[i].Color);
|
||||
|
|
|
@ -157,6 +157,8 @@ public:
|
|||
CMap();
|
||||
~CMap();
|
||||
|
||||
void AllocateTileset();
|
||||
|
||||
unsigned int getIndex(int x, int y) const
|
||||
{
|
||||
return x + y * this->Info.MapWidth;
|
||||
|
|
|
@ -349,6 +349,7 @@ extern CPlayer Players[PlayerMax]; /// All players
|
|||
extern CPlayer *ThisPlayer; /// Player on local computer
|
||||
extern bool NoRescueCheck; /// Disable rescue check
|
||||
extern std::vector<std::vector<CColor>> PlayerColorsRGB; /// Player colors
|
||||
extern std::vector<std::vector<SDL_Color>> PlayerColorsSDL; /// Player colors
|
||||
extern std::vector<std::string> PlayerColorNames; /// Player color names
|
||||
|
||||
extern PlayerRace PlayerRaces; /// Player races
|
||||
|
|
|
@ -139,22 +139,14 @@ extern void PrintOnStdOut(const char *format, ...);
|
|||
/**
|
||||
** Assert a condition. If cond is not true abort with file,line.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define Assert(cond) \
|
||||
do { if (EnableAssert && !(cond)) { AbortAt(__FILE__, __LINE__, __func__, #cond); }} while (0)
|
||||
#else
|
||||
#define Assert(cond)
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Print debug information with function name.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define DebugPrint(args) \
|
||||
do { if (EnableDebugPrint) { PrintFunction(); PrintOnStdOut(args); } } while (0)
|
||||
#else
|
||||
#define DebugPrint(args)
|
||||
#endif
|
||||
|
||||
/*============================================================================
|
||||
== Definitions
|
||||
|
|
|
@ -469,6 +469,8 @@ public:
|
|||
bool HardwareCursor; /// If true, uses the hardware to draw the cursor. Shaders do no longer apply to the cursor, but this way it's decoupled from the game refresh rate
|
||||
bool SelectionRectangleIndicatesDamage; /// If true, the selection rectangle interpolates color to indicate damage
|
||||
|
||||
int FrameSkip; /// Mask used to skip rendering frames (useful for slow renderers that keep up with the game logic, but not the rendering to screen like e.g. original Raspberry Pi)
|
||||
|
||||
int ShowOrders; /// How many second show orders of unit on map.
|
||||
int ShowNameDelay; /// How many cycles need to wait until unit's name popup will appear.
|
||||
int ShowNameTime; /// How many cycles need to show unit's name popup.
|
||||
|
|
|
@ -174,7 +174,7 @@ public:
|
|||
// minor programmatic editing features
|
||||
void OverlayGraphic(CGraphic *other, bool mask = false);
|
||||
|
||||
inline bool IsLoaded() const { return Surface != NULL; }
|
||||
inline bool IsLoaded(bool flipped = false) const { return Surface != NULL && (!flipped || SurfaceFlip != NULL); }
|
||||
|
||||
//guichan
|
||||
virtual void *_getData() const { return Surface; }
|
||||
|
|
|
@ -327,15 +327,17 @@ CMap::~CMap()
|
|||
delete Tileset;
|
||||
}
|
||||
|
||||
void CMap::AllocateTileset()
|
||||
{
|
||||
Assert(!Tileset);
|
||||
Tileset = new CTileset();
|
||||
}
|
||||
|
||||
/**
|
||||
** Alocate and initialise map table
|
||||
*/
|
||||
void CMap::Create()
|
||||
{
|
||||
if (!Tileset) {
|
||||
Tileset = new CTileset;
|
||||
}
|
||||
|
||||
Assert(!this->Fields);
|
||||
|
||||
this->Fields = new CMapField[this->Info.MapWidth * this->Info.MapHeight];
|
||||
|
@ -363,9 +365,7 @@ void CMap::Clean(const bool isHardClean /* = false*/)
|
|||
this->Info.Clear();
|
||||
this->Fields = NULL;
|
||||
this->NoFogOfWar = false;
|
||||
if (Tileset) {
|
||||
this->Tileset->clear();
|
||||
}
|
||||
this->Tileset->clear();
|
||||
this->TileModelsFileName.clear();
|
||||
CGraphic::Free(this->TileGraphic);
|
||||
this->TileGraphic = NULL;
|
||||
|
|
|
@ -501,8 +501,8 @@ void CMinimap::Destroy()
|
|||
MinimapSurface = NULL;
|
||||
}
|
||||
if (MinimapFogSurface && MinimapFogSurface->format != NULL) {
|
||||
// SDL_FreeSurface(MinimapFogSurface);
|
||||
MinimapSurface = NULL;
|
||||
SDL_FreeSurface(MinimapFogSurface);
|
||||
MinimapFogSurface = NULL;
|
||||
}
|
||||
delete[] Minimap2MapX;
|
||||
Minimap2MapX = NULL;
|
||||
|
|
|
@ -836,7 +836,6 @@ static int CclLoadTileModels(lua_State *l)
|
|||
*/
|
||||
static int CclDefineTileset(lua_State *l)
|
||||
{
|
||||
Map.Create();
|
||||
Map.Tileset->parse(l);
|
||||
|
||||
// Load and prepare the tileset
|
||||
|
|
|
@ -83,7 +83,7 @@ extern NumberDesc *Damage; /// Damage calculation for missile.
|
|||
*/
|
||||
void MissileType::LoadMissileSprite()
|
||||
{
|
||||
if (this->G && !this->G->IsLoaded()) {
|
||||
if (this->G && !this->G->IsLoaded(this->Flip)) {
|
||||
this->G->Load();
|
||||
if (this->Flip) {
|
||||
this->G->Flip();
|
||||
|
@ -495,7 +495,7 @@ static int MissileVisibleInViewport(const CViewport &vp, const Missile &missile)
|
|||
void MissileType::DrawMissileType(int frame, const PixelPos &pos) const
|
||||
{
|
||||
#ifdef DYNAMIC_LOAD
|
||||
if (!this->G->IsLoaded()) {
|
||||
if (!this->G->IsLoaded(this->Flip)) {
|
||||
((MissileType*)this)->LoadMissileSprite();
|
||||
}
|
||||
#endif
|
||||
|
@ -540,7 +540,7 @@ void Missile::DrawMissile(const CViewport &vp) const
|
|||
// FIXME: I should copy SourcePlayer for second level missiles.
|
||||
if (sunit && sunit->Player) {
|
||||
#ifdef DYNAMIC_LOAD
|
||||
if (!this->Type->G->IsLoaded()) {
|
||||
if (!this->Type->G->IsLoaded(this->Type->Flip)) {
|
||||
((MissileType*)this->Type)->LoadMissileSprite();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -558,7 +558,7 @@ static inline int CostMoveTo(unsigned int index, const CUnit &unit)
|
|||
}
|
||||
*c = CostMoveToCallBack_Default(index, unit) + 1;
|
||||
#ifdef DEBUG
|
||||
Assert(c >= 0);
|
||||
Assert(*c >= 0);
|
||||
#endif
|
||||
return *c - 1;
|
||||
}
|
||||
|
|
|
@ -63,13 +63,6 @@ bool CallbackMusic; /// flag true callback ccl if stops
|
|||
*/
|
||||
static void MusicFinishedCallback()
|
||||
{
|
||||
static long MusicCallbackDebounce = 0;
|
||||
long ticks = SDL_GetTicks();
|
||||
if (MusicCallbackDebounce + 1000 < ticks) {
|
||||
// only accept music finished callbacks for music playing longer than 1s
|
||||
return;
|
||||
}
|
||||
MusicCallbackDebounce = ticks;
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = SDL_SOUND_FINISHED;
|
||||
|
|
|
@ -269,17 +269,10 @@ bool UnitSoundIsPlaying(Origin *origin)
|
|||
*/
|
||||
static void ChannelFinished(int channel)
|
||||
{
|
||||
static long ChannelCallbackDebounce[MaxChannels] = {0};
|
||||
if (channel < 0 || channel >= MaxChannels) {
|
||||
fprintf(stderr, "ERROR: Out of bounds channel (how?)\n");
|
||||
return;
|
||||
}
|
||||
long ticks = SDL_GetTicks();
|
||||
if (ChannelCallbackDebounce[channel] + 200 < ticks) {
|
||||
// only accept sound finished callbacks for sounds playing longer than 0.2s
|
||||
return;
|
||||
}
|
||||
ChannelCallbackDebounce[channel] = ticks;
|
||||
if (Channels[channel].FinishedCallback != NULL) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
|
@ -387,18 +380,6 @@ static Mix_Music *LoadMusic(const char *name)
|
|||
return currentMusic;
|
||||
}
|
||||
|
||||
static Mix_Chunk *LoadSample(const char *name)
|
||||
{
|
||||
#ifdef DYNAMIC_LOAD
|
||||
Mix_Chunk *r = (Mix_Chunk *)calloc(sizeof(Mix_Chunk), 1);
|
||||
r->allocated = 0xcafebeef;
|
||||
r->abuf = (Uint8 *)(strdup(name));
|
||||
return r;
|
||||
#else
|
||||
return ForceLoadSample(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Mix_Chunk *ForceLoadSample(const char *name)
|
||||
{
|
||||
Mix_Chunk *r = Mix_LoadWAV(name);
|
||||
|
@ -414,6 +395,18 @@ static Mix_Chunk *ForceLoadSample(const char *name)
|
|||
return Mix_LoadWAV_RW(f->as_SDL_RWops(), 1);
|
||||
}
|
||||
|
||||
static Mix_Chunk *LoadSample(const char *name)
|
||||
{
|
||||
#ifdef DYNAMIC_LOAD
|
||||
Mix_Chunk *r = (Mix_Chunk *)calloc(sizeof(Mix_Chunk), 1);
|
||||
r->allocated = 0xcafebeef;
|
||||
r->abuf = (Uint8 *)(strdup(name));
|
||||
return r;
|
||||
#else
|
||||
return ForceLoadSample(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
** Load a music file
|
||||
**
|
||||
|
@ -650,7 +643,7 @@ bool IsMusicEnabled()
|
|||
*/
|
||||
bool IsMusicPlaying()
|
||||
{
|
||||
return Mix_PlayingMusic();
|
||||
return Mix_PlayingMusic() || External_IsPlaying();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -398,6 +398,7 @@ void FreePlayerColors()
|
|||
Players[i].ClearUnitColors();
|
||||
}
|
||||
PlayerColorsRGB.clear();
|
||||
PlayerColorsSDL.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1303,10 +1304,8 @@ void GraphicPlayerPixels(int colorIndex, const CGraphic &sprite)
|
|||
*/
|
||||
void SetPlayersPalette()
|
||||
{
|
||||
PlayerColorsSDL.clear();
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
Players[i].SetUnitColors(PlayerColorsRGB[i]);
|
||||
PlayerColorsSDL.push_back(std::vector<SDL_Color>(PlayerColorsRGB[i].begin(), PlayerColorsRGB[i].end()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -868,6 +868,7 @@ static int CclDefinePlayerColors(lua_State *l)
|
|||
if (nargs < 2 || LuaToBoolean(l, 2)) {
|
||||
PlayerColorNames.clear();
|
||||
PlayerColorsRGB.clear();
|
||||
PlayerColorsSDL.clear();
|
||||
if (args / 2 < PlayerMax - 1) { // accept no color for neutral player
|
||||
LuaError(l, "You need to define at least %d colors" _C_ PlayerMax - 1);
|
||||
}
|
||||
|
@ -896,6 +897,7 @@ static int CclDefinePlayerColors(lua_State *l)
|
|||
lua_pop(l, 1);
|
||||
}
|
||||
PlayerColorsRGB.push_back(newColors);
|
||||
PlayerColorsSDL.push_back(std::vector<SDL_Color>(newColors.begin(), newColors.end()));
|
||||
}
|
||||
|
||||
if (defaultNeutralPlayer) {
|
||||
|
@ -906,6 +908,7 @@ static int CclDefinePlayerColors(lua_State *l)
|
|||
neutralColors.push_back(neutralColor);
|
||||
}
|
||||
PlayerColorsRGB.push_back(neutralColors);
|
||||
PlayerColorsSDL.push_back(std::vector<SDL_Color>(neutralColors.begin(), neutralColors.end()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -936,6 +939,7 @@ static int CclDefinePlayerColorIndex(lua_State *l)
|
|||
PlayerColorIndexCount = LuaToNumber(l, 2);
|
||||
|
||||
PlayerColorsRGB.clear();
|
||||
PlayerColorsSDL.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ void Exit(int err)
|
|||
FreeButtonStyles();
|
||||
FreeAllContainers();
|
||||
freeGuichan();
|
||||
fprintf(stdout, "Frames %lu, Slow frames %d = %ld%%\n",
|
||||
fprintf(stdout, "Frames %lu, Slow frames %ld = %ld%%\n",
|
||||
FrameCounter, SlowFrameCounter,
|
||||
(SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1));
|
||||
lua_settop(Lua, 0);
|
||||
|
@ -752,6 +752,8 @@ int stratagusMain(int argc, char **argv)
|
|||
InitMusic();
|
||||
}
|
||||
|
||||
// init globals
|
||||
Map.AllocateTileset();
|
||||
UnitManager = new CUnitManager();
|
||||
FogOfWar = new CFogOfWar();
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ class CPreference
|
|||
bool HardwareCursor;
|
||||
bool SelectionRectangleIndicatesDamage;
|
||||
|
||||
unsigned int FrameSkip;
|
||||
|
||||
unsigned int ShowOrders;
|
||||
unsigned int ShowNameDelay;
|
||||
unsigned int ShowNameTime;
|
||||
|
|
|
@ -331,6 +331,7 @@ static int CclUnit(lua_State *l)
|
|||
}
|
||||
|
||||
CUnit *unit = &UnitManager->GetSlotUnit(slot);
|
||||
bool hadType = unit->Type != NULL;
|
||||
CUnitType *type = NULL;
|
||||
CUnitType *seentype = NULL;
|
||||
CPlayer *player = NULL;
|
||||
|
@ -645,6 +646,15 @@ static int CclUnit(lua_State *l)
|
|||
MapMarkUnitSight(*unit);
|
||||
}
|
||||
|
||||
if (!hadType && unit->Container) {
|
||||
// this unit was assigned to a container before it had a type, so we
|
||||
// need to actually add it now, since only with a type do we know the
|
||||
// BoardSize it takes up in the container
|
||||
CUnit *host = unit->Container;
|
||||
unit->Container = NULL;
|
||||
unit->AddInContainer(*host);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ extern int ExtraDeathIndex(const char *death);
|
|||
*/
|
||||
void CUnit::RefsIncrease()
|
||||
{
|
||||
Assert(Refs && !Destroyed);
|
||||
Assert(!Refs || (Refs && !Destroyed));
|
||||
if (!SaveGameLoading) {
|
||||
++Refs;
|
||||
}
|
||||
|
@ -1093,16 +1093,21 @@ void CUnit::AddInContainer(CUnit &host)
|
|||
{
|
||||
Assert(Container == NULL);
|
||||
Container = &host;
|
||||
if (!Type) {
|
||||
// if we're loading a game, the Type may not have been initialized
|
||||
// yet. so we ignore this and the unit gets added later when it is
|
||||
// loaded via CclUnit
|
||||
return;
|
||||
}
|
||||
if (host.InsideCount == 0) {
|
||||
NextContained = PrevContained = this;
|
||||
host.UnitInside = this;
|
||||
} else {
|
||||
// keep sorted by size.
|
||||
// FIXME: if we're loading a game, the Type may not have been initialized yet!!
|
||||
int mySize = Type ? Type->BoardSize : 1;
|
||||
int mySize = Type->BoardSize;
|
||||
NextContained = host.UnitInside;
|
||||
bool becomeFirst = true;
|
||||
while (NextContained->Type ? NextContained->Type->BoardSize : 1 > mySize) {
|
||||
while (NextContained->Type->BoardSize > mySize) {
|
||||
becomeFirst = false;
|
||||
NextContained = NextContained->NextContained;
|
||||
if (NextContained == host.UnitInside) {
|
||||
|
|
|
@ -630,7 +630,9 @@ static void DrawDecoration(const CUnit &unit, const CUnitType &type, const Pixel
|
|||
int y = screenPos.y;
|
||||
#ifdef DEBUG
|
||||
// Show the number of references.
|
||||
CLabel(GetGameFont()).DrawClip(x + 1, y + 1, unit.Refs);
|
||||
if (EnableDebugPrint) {
|
||||
CLabel(GetGameFont()).DrawClip(x + 1, y + 1, unit.Refs);
|
||||
}
|
||||
#endif
|
||||
|
||||
UpdateUnitVariables(const_cast<CUnit &>(unit));
|
||||
|
|
|
@ -719,9 +719,6 @@ const EventCallback *GetCallbacks()
|
|||
return Callbacks;
|
||||
}
|
||||
|
||||
static int SkipFrameMask = 0;
|
||||
static unsigned long NextSlowFrameReaction = FRAMES_PER_SECOND * 10;
|
||||
|
||||
/**
|
||||
** Wait for interactive input event for one frame.
|
||||
**
|
||||
|
@ -741,23 +738,6 @@ void WaitEventsOneFrame()
|
|||
Uint32 ticks = SDL_GetTicks();
|
||||
if (ticks > NextFrameTicks) { // We are too slow :(
|
||||
++SlowFrameCounter;
|
||||
if (SlowFrameCounter > NextSlowFrameReaction) {
|
||||
unsigned long pct = (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1);
|
||||
if (pct >= 60) {
|
||||
SkipFrameMask = 0b111;
|
||||
} else if (pct >= 40) {
|
||||
SkipFrameMask = 0b101;
|
||||
} else if (pct >= 20) {
|
||||
SkipFrameMask = 0b11;
|
||||
} else if (pct >= 10) {
|
||||
SkipFrameMask = 0b1;
|
||||
}
|
||||
NextSlowFrameReaction += FRAMES_PER_SECOND * 10;
|
||||
fprintf(stdout, "WARNING WARNING WARNING\n"
|
||||
"Frames %lu, Slow frames %d = %lu%%, starting to render only every %d%s frame.\n",
|
||||
FrameCounter, SlowFrameCounter, pct, SkipFrameMask + 1, SkipFrameMask == 1 ? "nd" : "th");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
InputMouseTimeout(*GetCallbacks(), ticks);
|
||||
|
@ -855,7 +835,7 @@ void RealizeVideoMemory()
|
|||
if (dummyRenderer) {
|
||||
return;
|
||||
}
|
||||
if (FrameCounter & SkipFrameMask) {
|
||||
if (Preference.FrameSkip && (FrameCounter & Preference.FrameSkip)) {
|
||||
return;
|
||||
}
|
||||
if (NumRects) {
|
||||
|
|
Loading…
Reference in a new issue