Object data without level-specific data
In my map World of Warcraft Reforged I had all hero ability levels set to a maximum of 100 to allow players much longer gameplay/leveling since the maximum hero level is 500 and you can skill 5 * 100 ability levels. However, this decreased the loading time massively from like 20-30 seconds to 2 minutes and for many players it led to a disconnect. First of all, the disconnect should be fixed in Reforged but the long loading time is still not acceptable especially if you have to rehost the game multiple times due to leavers.
Sure, I could reduce the XP rate but then you can skill an ability every 2 hours which is NO fun at all and since the number of hero abilities is limited and not every map has a custom skill system with unit abilities, this is not an option.
The long loading time is due to the many per level values in the object data. Widgetizing is annoying as well and the Widgetizer couldn't even handle the big number of ability level fields, so it crashed.
Hence, I had this simple idea based on how the research effects are handled in object data:
- Allow to set a boolean flag field per ability and research which says "No specific level values".
- If this value is set to true there is no DataA1, DataA2, DataA3 or Col1, Col2, Col3 fields etc. Instead you define the base value and a level factor value like for effects of Warcraft III researches. The actual value is calculated at runtime considering the current ability level for the unit/hero. It won't work for all types of fields like unit types or flags but for integers and reals which is enough for most abilities and researches with multiple levels.
- This would require more text placeholders for the current level like in the ability learn tooltip: "Blizzard - Level %d", so you can define only one tooltip text.
- To my knowledge the actual values are stored in memory per ability anyway since there are natives to retrieve and change the exact values per ability per unit at runtime. They could be calculated and stored whenever the ability level is changed for example when you call
This solution would allow you to create abilities and researches with like 5000 levels without any significant longer loading time.
They would probably load even faster than the current abilities and researches which have more than 1 level.
This feature would be really useful for maps with long gameplay and savecodes.
Currently, this can only be achieved with triggers by changing the stats of the ability per unit with the help of the new natives. I am not sure if you can change the tooltips without issues.
Standard Summon Ability with fields for the units stats
There are multiple summon abilities like Summon Water Elemental and Dark Portal.
All of them allow you to specify a unit type.
If the ability has many levels like 50 it would be too much work to create like 50 different unit types.
In my map I use a trigger which detects the summoning event and changes the stats of the unit due to the skilled ability level.
Blizzard could add a standard ability which lets you specify the unit type once and the stats bonuses per level like:
- HP bonus for summoned unit
- Mana bonus for summoned unit
- Damage Dices bonus for summoned unit
- etc.
This would work better if they added the feature I mentioned before with "no specific level value".
Dark Portal with Time Limit
We all know Archimonde's Dark Portal ability which is pretty awesome and useful. Just add a boolean flag "Limited Time" which considers the duration. I had to solve this issue with a trigger.
File API
Workarounds are currently used to read and write files in the directory "C:\Users\XXX\Documents\Warcraft III\CustomMapData" to store savecodes for example. Since we do it anyway, they could just provide these two simple natives:
JASS:
native WriteFile takes player whichPlayer, string name, string content return boolean
native ReadFile takes player whichPlayer, string name return string
Reading a file automatically synchronizes the content from one player only with the rest, so the resulting string is always sync. They could provide the natives without specifying the player and allow using GetLocalPlayer instead.
Joining Players
Certain maps could allow joining players. The flag could also be overwritten in the lobby of the game.
It would only need these two constants:
JASS:
constant playerevent EVENT_PLAYER_JOIN = ConvertPlayerEvent(xxx)
constant mapflag MAP_ALLOW_JOINING_PLAYERS = ConvertMapFlag(xxx)
The trigger player is joining the game and replacing an empty slot or the slot of a leaving player.
This would allow to host maps as servers like for other multiplayer games and make the games more interesting since they will find a running game with a changed map.
Sync changing level and game cache
Allow changing levels with game cache data which is synchronous for all players. The level map is downloaded from one player and the game cache data is also synchronized from one player. This allows to play something like the Bonus Campaign in multiplayer.
JASS:
native ChangeLevelSync takes player host, string newLevel returns nothing
native LoadGameSync takes player host, string saveFileName returns
Both files will force the other players to download the new level and save file from the specified host player if they do not have it already.
Allow to use natives like SaveGame, RenameSaveDirectory, RemoveSaveDirectory, CopySaveGame and SaveGameExists
to be used with GetLocalPlayer to do it only for the host, for example.
This would allow the specified host player to create the save games etc. just before changing the level.
For the game caches it would require the following natives:
JASS:
native ReloadGameCachesFromDiskSync takes player host returns boolean
native InitGameCacheSync takes player host, string campaignFile returns gamecache
native SaveGameCacheSync takes player host, gamecache whichCache returns boolean
Again the game cache file is downloaded from the specified host player and synchronized with all other players.
This would allow to store and load hero data from the previous level.
I think with these few natives you would change the possibilities of multiplayer campaigns, RPG servers etc. massively. I guess it will never happen.
Extended Warcraft III files per map/campaign
Allow extending existing files from Warcraft III in maps and campaigns. This would help adding additional entries without removing the default ones.
The following files could be extended:
- common.j
- common.ai
- Blizzard.j
- TriggerData.txt
- TriggerStrings.txt
- All SLK files (for example soundsets, unit data etc.)
The "extend" option could be set in the "Import Manager"/"Asset Manager" per file. The file would not overwrite the existing file from Warcraft III but would just extend its content.
This feature would allow custom sound sets, global AI script functions, custom GUI functions, widgetized object data etc. etc. without the requirement of merging and updating files whenever Warcraft III is updated. It would make life as a modder so much easier.
Research to reduce/change training/building/upgrading/stock replenish interval time and stock maximum of unit types and item types
It would be nice to allow such an affect per unit and item type and it would only affect the buildings which have the research configured.
Team colored icons
Many icons have parts in it which are the team color of the unit. It should be possible to mark icon areas as team colors, maybe with a special color value or alpha. These areas should have the team color of the buying unit/building unit/selected unit etc.
Path API
The API allows you to check if areas are reachable and to understand how Warcraft will calculate the paths of units.
JASS:
type path extends handle
// could also use movetype instead
native GetPath takes real sourceX, real sourceY, real targetX, real targetY, pathingtype t returns path
native DestroyPath takes path p returns nothing
native GetPathSize takes path p returns integer
native GetPathPosX takes path p, integer index returns real
native GetPathPosY takes path p, integer index returns real
Attack Cooldown API
JASS:
native SetUnitAttackCooldown takes unit whichUnit, integer index, real cooldown returns nothing
native GetUnitAttackCooldown takes unit whichUnit, integer index returns real
native ResetUnitAttackCooldown takes unit whichUnit, integer index returns nothing
Extended UI API
Allow to have more space in the UI and to use custom race UIs. Custom races support would be even better.
JASS:
// some of them are probably possible by getting the ability but this would be easier to use
native UnitHideAttackAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideMoveAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideStopAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideHaltAbility takes unit whichUnit, boolean flag returns nothing
native UnitHidePatrolAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideRallyPointAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideSelectUserAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideSelectHeroAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideHeroSkillsAbility takes unit whichUnit, boolean flag returns nothing
native UnitHideBuildAbility takes unit whichUnit, boolean flag returns nothing
// can be used with GetLocalPlayer:
function SetAreaOfEffectModel takes string model returns nothing
function SetAreaOfEffectTexture takes string texture returns nothing
function SetRallyPointModel takes string model returns nothing
function SetRallyPointTexture takes string texture returns nothing
// more generic game interface API with GetLocalPlayer:
type gameinterfaceintegerfield extends handle
type gameinterfacestringfield extends handle
type gameinterfacebooleanfield extends handle
type gameinterfacerealfield extends handle
native SetGameInterfaceString takes gameinterfacestringfield whichField, string value returns nothing
native GetGameInterfaceString takes gameinterfacestringfield whichField returns string
native SetGameInterfaceInteger takes gameinterfaceintegerfield whichField, integer value returns nothing
native GetGameInterfaceInteger takes gameinterfaceintegerfield whichField returns integer
native SetGameInterfaceBoolean takes gameinterfacebooleanfield whichField, boolean value returns nothing
native GetGameInterfaceBoolean takes gameinterfacebooleanfield whichField returns boolean
native SetGameInterfaceReal takes gameinterfacerealfield whichField, integer real value returns nothing
native GetGameInterfaceReal takes gameinterfacerealfield whichField returns real
Event API
JASS:
// triggers when the item is actually dropped, the same could be supported for an item pawn event (before and after events)
constant playerunitevent EVENT_PLAYER_UNIT_DROP_ITEM_DONE = ConvertPlayerUnitEvent(XXX)
constant unitevent EVENT_UNIT_DROP_ITEM_DONE = ConvertUnitEvent(XXX)
constant playerunitevent EVENT_PLAYER_UNIT_BUFF_ADDED = ConvertPlayerUnitEvent(XXX)
constant unitevent EVENT_UNIT_BUFF_ADDED = ConvertUnitEvent(XXX)
constant playerunitevent EVENT_PLAYER_UNIT_BUFF_REMOVED = ConvertPlayerUnitEvent(XXX)
constant unitevent EVENT_UNIT_BUFF_REMOVED = ConvertUnitEvent(XXX)
native GetTriggerBuffSource takes nothing returns unit
native GetTriggerBuff takes nothing returns integer
Hero Skill API
The maximum number of hero abilities should not be 5. It should simply be unlimited even if they are not shown.
JASS:
native SetHeroMaximumSkills takes unit hero, integer maximum returns nothing
native GetHeroMaximumSkills takes unit hero returns integer
native GetHeroSkill takes unit hero, integer index returns integer
native GetHeroSkillCount takes unit hero returns integer
native ReplaceHeroSkill takes unit hero, integer old, integer new returns nothing
Plugin API
Plugins could be written for example in C/C++ and be placed in the players directories. They do not have to be enabled for all players at the same time in the same game. Plugins can retrieve data from the running game and send data from the running game. The player is always a parameter.
JASS:
// returns if the player has the
native PlayerHasPlugin takes player whichPlayer, string pluginDllName returns boolean
native GetPlayerPluginVersion takes player whichPlayer, string pluginDllName returns string
native SendPluginData takes player whichPlayer, string pluginDllName, string data0, string data1, string data2, string data3 returns boolean
native TriggerRegisterPluginReceiveData takes trigger whichTrigger returns event
// GetTriggerPlayer is the player whose plugin the data is sent from
native GetPluginDllName takes nothing returns string
native GetPluginData0 takes nothing returns string
native GetPluginData1 takes nothing returns string
native GetPluginData2 takes nothing returns string
native GetPluginData3 takes nothing returns string
In C++ you will somehow have to define the version or it is extracted from the DLL. The plugins would make it easier to transfer game data like into files/databases/live stats of games etc. etc. They could also make really fast calculations.