├── .editorconfig ├── .gitignore ├── .gitmodules ├── .mdformat.toml ├── .stylua.toml ├── .styluaignore ├── CHANGELOG.md ├── README.md ├── _build ├── blizzard.j └── common.j ├── docs ├── settings.md └── special-thanks.md ├── etc └── gem.lua ├── lib ├── gem │ ├── date.lua │ ├── deep_copy.lua │ └── id.lua └── patch │ ├── 1.26.0 │ ├── blizzard.j │ └── common.j │ ├── 1.27.0 │ ├── 1.27.1 │ ├── 1.28.0 │ ├── 1.28.1 │ ├── 1.28.2 │ ├── 1.28.3 │ ├── 1.28.4 │ ├── 1.28.5 │ ├── 1.29.0 │ ├── blizzard.j │ └── common.j │ ├── 1.29.1 │ ├── 1.29.2 │ ├── blizzard.j │ └── common.j │ ├── 1.30.0 │ ├── blizzard.j │ └── common.j │ ├── 1.30.1 │ ├── 1.30.2 │ ├── blizzard.j │ └── common.j │ ├── 1.30.3 │ ├── 1.30.4 │ ├── 1.31.0 │ ├── blizzard.j │ ├── common.ai │ └── common.j │ ├── 1.31.1 │ ├── blizzard.j │ ├── common.ai │ └── common.j │ └── README.md ├── share ├── constants │ ├── gameplay │ │ └── gem.lua │ └── interface │ │ ├── gem.lua │ │ └── upkeep.lua ├── environment │ ├── fix-games-list.lua │ ├── header-loading-screen.lua │ ├── lobby.lua │ └── version.lua ├── hide-buttons.lua ├── imports │ ├── import-directory.lua │ └── map │ │ ├── FullScreen.blp │ │ ├── Gem │ │ ├── Armor │ │ │ ├── Blazed.blp │ │ │ ├── Blue.blp │ │ │ ├── Bryvx.blp │ │ │ ├── Green.blp │ │ │ ├── Pink.blp │ │ │ ├── Red.blp │ │ │ ├── White.blp │ │ │ └── Yellow.blp │ │ └── Attack │ │ │ ├── Amethyst.blp │ │ │ ├── Diamond.blp │ │ │ ├── Emerald.blp │ │ │ ├── Ruby.blp │ │ │ ├── Sapphire.blp │ │ │ ├── Topaz.blp │ │ │ └── Water.blp │ │ ├── LoadingScreen.mdx │ │ ├── ReplaceableTextures │ │ ├── CommandButtonsDisabled │ │ │ ├── DISPASOrbOfDarkness.blp │ │ │ └── DISPASStaffOfNegation.blp │ │ └── PassiveButtons │ │ │ ├── PASBTNGems.blp │ │ │ ├── PASOrbOfDarkness.blp │ │ │ └── PASStaffOfNegation.blp │ │ └── Units │ │ └── CommandFunc.txt ├── maps │ └── Gem TD Plus.w3x ├── objects │ ├── air-slate.lua │ ├── anti-stuck-cooldown.lua │ ├── black-opal.lua │ ├── bonus-armor.lua │ ├── boss.lua │ ├── buff-icons.lua │ ├── builder.lua │ ├── change-topaz-base.lua │ ├── cheats.lua │ ├── combine-special-button.lua │ ├── critter.lua │ ├── dark-emerald-chain.lua │ ├── difficulty-armor-changes.lua │ ├── dummy-caster.lua │ ├── emerald-poison-kill.lua │ ├── fix-lumber-costs.lua │ ├── gold-mine-buttons.lua │ ├── great-amethyst.lua │ ├── jade.lua │ ├── kill-bonus-remove-brilliance-aura.lua │ ├── kill-bonus-remove-spell-immunity.lua │ ├── make-slates-repairable.lua │ ├── mine.lua │ ├── monster-names.lua │ ├── nerf-wraith.lua │ ├── normal.lua │ ├── paraiba.lua │ ├── pink-diamond.lua │ ├── pink.lua │ ├── place-gem.lua │ ├── range-check.lua │ ├── remove-rock.lua │ ├── ruby-splash.lua │ ├── selection.lua │ ├── selection │ │ ├── combine.lua │ │ └── slate.lua │ ├── slate-teleport.lua │ ├── slate │ │ ├── ancient.lua │ │ ├── elder.lua │ │ ├── poison.lua │ │ ├── spell.lua │ │ └── viper.lua │ ├── specials │ │ ├── blood-stone │ │ │ ├── 01-blood-stone.lua │ │ │ └── 02-ancient-blood-stone.lua │ │ ├── malachite │ │ │ ├── 01-malachite.lua │ │ │ ├── 02-vivid-malachite.lua │ │ │ └── 03-mighty-malachite.lua │ │ ├── red-crystal │ │ │ └── 03-rose-quartz-crystal.lua │ │ ├── silver │ │ │ ├── 01-silver.lua │ │ │ ├── 02-sterling-silver.lua │ │ │ └── 03-silver-knight.lua │ │ ├── star-ruby │ │ │ ├── 01-star-ruby.lua │ │ │ ├── 02-blood-star.lua │ │ │ └── 03-fire-star.lua │ │ ├── stone-of-bryvx.lua │ │ ├── uranium.lua │ │ ├── uranium │ │ │ └── immolation.lua │ │ └── yellow-sapphire │ │ │ ├── 01-yellow-sapphire.lua │ │ │ └── 02-star-yellow-sapphire.lua │ ├── standardize-slate-range.lua │ ├── stone-of-bryvx.lua │ ├── swap.lua │ ├── switch-info-button-location.lua │ ├── type-projectiles.lua │ ├── unit-disarm.lua │ ├── unit-event.lua │ ├── unit-state.lua │ ├── unit-stun.lua │ ├── unlock-barrage-cap.lua │ ├── unused-objects.lua │ └── update-map-information.lua └── tooltips.lua ├── src ├── array.j ├── board.j ├── cheats.j ├── clock.j ├── color.j ├── commands.j ├── commands │ ├── bars.j │ ├── debug.j │ ├── extra.j │ ├── maze.j │ └── zoom.j ├── config.j ├── detect-placed-gem-death.j ├── dummy-caster.j ├── effect.j ├── error.j ├── fix │ ├── dialog-user-control.j │ ├── stuck-tooltip.j │ └── upgrade-scale.j ├── game-status.j ├── game.j ├── gem-3.1.j ├── gem-3.1 │ ├── common_.j │ ├── find-ability-levels.j │ ├── globals.j │ ├── miner-flashing.j │ └── movement.j ├── gem.j ├── gem │ ├── chance.j │ ├── combination.j │ ├── combination │ │ └── marker.j │ ├── critters.j │ ├── extra-chance.j │ ├── extra-chance │ │ ├── menu.j │ │ └── menu │ │ │ ├── slate.j │ │ │ └── type.j │ ├── gems.j │ ├── ground-textures.j │ ├── immolation.j │ ├── information.j │ ├── information │ │ ├── changelogs.j │ │ ├── initialize.j │ │ ├── random-information.j │ │ └── what-is-gem-td-plus.j │ ├── mine.j │ ├── mine │ │ ├── cancel.j │ │ ├── information.j │ │ ├── slate.j │ │ └── type.j │ ├── movement.j │ ├── placement.j │ ├── player.j │ ├── quality.j │ ├── rank.j │ ├── recipe.j │ ├── selection.j │ ├── selection │ │ ├── combine.j │ │ ├── downgrade.j │ │ ├── initialize.j │ │ ├── keep.j │ │ ├── marker.j │ │ ├── slate.j │ │ ├── slate │ │ │ └── marker.j │ │ └── special.j │ ├── slate.j │ ├── slate │ │ ├── ancient.j │ │ ├── damage.j │ │ ├── elder.j │ │ ├── hold.j │ │ ├── initialize.j │ │ ├── poison.j │ │ ├── spell.j │ │ ├── stacking.j │ │ └── viper.j │ ├── spawn.j │ ├── special.j │ ├── special │ │ ├── blood-stone.j │ │ ├── dark-emerald.j │ │ ├── initialize.j │ │ ├── jade.j │ │ ├── red-crystal.j │ │ ├── star-ruby.j │ │ ├── star-ruby │ │ │ └── 03-fire-star.j │ │ ├── tourmaline.j │ │ └── uranium.j │ ├── swap.j │ ├── type.j │ └── version.j ├── handle.j ├── hashtable.j ├── id.j ├── log.j ├── main.j ├── natives.j ├── node.j ├── player-color.j ├── preload.j ├── quest.j ├── run.j ├── settings │ ├── common_.j │ ├── initialize.j │ └── setup.j ├── spawn-group.j ├── spawn.j ├── string.j ├── table.j ├── time.j ├── trigger.j ├── unit │ ├── bonus │ │ └── armor.j │ ├── damage.j │ ├── disarm.j │ ├── event.j │ ├── event │ │ ├── death.j │ │ ├── enters.j │ │ ├── initialize.j │ │ └── leaves.j │ ├── indexer.j │ ├── state.j │ ├── stun.j │ └── user-data.j └── zeta.j └── tmp └── .gitignore /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | max_line_length = 76 7 | indent_style = tab 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | indent_style = space 14 | 15 | [*.j] 16 | max_line_length = off 17 | 18 | [*.wts] 19 | end_of_line = crlf 20 | max_line_length = off 21 | 22 | [COMMIT_EDITMSG] 23 | max_line_length = 72 24 | indent_style = space 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | wurst 3 | wurst.dependencies 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "map"] 2 | path = map 3 | url = git@github.com:nvs/map.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /.mdformat.toml: -------------------------------------------------------------------------------- 1 | wrap = 74 2 | number = true 3 | end_of_line = 'lf' 4 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | syntax = 'All' 2 | column_width = 76 3 | line_endings = 'Unix' 4 | indent_type = 'Tabs' 5 | indent_width = 4 6 | quote_style = 'ForceSingle' 7 | call_parentheses = 'Always' 8 | space_after_function_names = 'Definitions' 9 | collapse_simple_statement = 'Never' 10 | 11 | [sort_requires] 12 | enabled = true 13 | -------------------------------------------------------------------------------- /.styluaignore: -------------------------------------------------------------------------------- 1 | map/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gem Tower Defense Plus 2 | 3 | ## Contents 4 | 5 | - [Overview](#overview) 6 | - [How to Play](#how-to-play) 7 | - [Changelog](#changelog) 8 | - [Development](#development) 9 | 10 | ## Overview 11 | 12 | Gem TD+ is an updated version of Gem Tower Defense, a map originally 13 | created by Bryvx. It aims to enhance the existing gameplay while 14 | introducing new features, possibilities, and strategies. 15 | 16 | The [GitHub] repository is oriented more towards development of the map. 17 | If that is of interest to you, please consider creating an account and 18 | participating. Feedback and contributions are always welcome. 19 | 20 | To learn the latest community news, meet other players, or view the active 21 | leaderboards, one should visit the [Discord]. It aims to serve as the 22 | focal point for all things Gem TD+. 23 | 24 | The [Leaderboards] repository is the official source of leaderboard 25 | information. It contains the screenshots and replays for all games that 26 | are currently, or were formerly, on the leaderboards, both past and 27 | present. Various useful information, including details of how to submit 28 | games and view replays, is also available. 29 | 30 | ## How to Play 31 | 32 | Head over to [releases] and find the version of the map you wish to play. 33 | It is recommened to play the [latest release]. Gem TD+ is compatible with 34 | the latest Warcraft III patch. No efforts are made to maintain 35 | compatibility with older patches. 36 | 37 | ## Changelog 38 | 39 | The [changelog](CHANGELOG.md) is written with the perspective of the 40 | player in mind. As such, it will be void of many changes that affect 41 | development of the map. For that information, please consult the commit 42 | log. 43 | 44 | ### Pre-release 45 | 46 | In the event that you are looking for the changelog of a testing version, 47 | please visit [releases]. A link to that testing version's changelog should 48 | be included in the description. 49 | 50 | ## Development 51 | 52 | Current development of Gem TD+ relies upon [Map]. This dependency is 53 | included as a Git submodule, so please consult the Git documentation for 54 | assistance in that regard. Also, be sure to satisfy the dependencies of 55 | Map. 56 | 57 | The following command can be used to clone the repository: 58 | 59 | ```sh 60 | git clone --recurse-submodule https://github.com/nvs/gem.git 61 | ``` 62 | 63 | And from the project's root directory, building the map can be done with: 64 | 65 | ```sh 66 | lua map/build etc/gem.lua 67 | ``` 68 | 69 | For more details on how to use Map, please consult its documentation. Of 70 | course, how to invoke the tools will vary depending on your setup. 71 | 72 | _Note that the process used to the build the map has changed over time. 73 | When attempting to build older versions one should consult the file 74 | `docs/building-the-map.md`. This file will not exist in more recent 75 | versions._ 76 | 77 | [discord]: https://discord.gg/PxNNp77 78 | [github]: https://github.com/nvs/gem 79 | [latest release]: https://github.com/nvs/gem/releases/latest 80 | [leaderboards]: https://github.com/nvs/gem-leaderboards 81 | [map]: https://github.com/nvs/map 82 | [releases]: https://github.com/nvs/gem/releases 83 | -------------------------------------------------------------------------------- /_build/blizzard.j: -------------------------------------------------------------------------------- 1 | ../lib/patch/1.31.0/blizzard.j -------------------------------------------------------------------------------- /_build/common.j: -------------------------------------------------------------------------------- 1 | ../lib/patch/1.31.0/common.j -------------------------------------------------------------------------------- /docs/settings.md: -------------------------------------------------------------------------------- 1 | # Gem TD+ Settings 2 | 3 | As of Gem TD+ 1.5.0 there are no selectable settings. This may change in 4 | future versions. 5 | 6 | ## HostBot Command Library (HCL) 7 | 8 | In versions prior to Gem TD+ 1.5.0, a value of `0` would represent the default 9 | setting for each available category. This will continue to remain the case. 10 | However, as there are no settings now it serves no functional purpose. 11 | -------------------------------------------------------------------------------- /docs/special-thanks.md: -------------------------------------------------------------------------------- 1 | # Special Thanks 2 | 3 | First of all, a big thank you to everyone who has played Gem TD over the years 4 | and helped it continue to thrive as a map we all love and enjoy. 5 | 6 | ## Gem Tower Defense Plus 7 | 8 | The following people deserve recognition for their support in the making of 9 | Gem TD+: 10 | 11 | - bunnyjean 12 | - Sesamia 13 | - Arsenic 14 | - DMVPDemonMOM 15 | 16 | ## Gem Tower Defense 17 | 18 | Recognition needs to be given to those who supported Bryvx in the making of 19 | Gem TD: 20 | 21 | - turbopower 22 | - MafaBaby 23 | - DMVPDemonMOM 24 | - Ghost-007 25 | - Vinxu 26 | - Spiriax 27 | -------------------------------------------------------------------------------- /etc/gem.lua: -------------------------------------------------------------------------------- 1 | return { 2 | input = 'share/maps/Gem TD Plus.w3x', 3 | 4 | output = { 5 | directories = { 6 | build = 'tmp', 7 | optimize = 'tmp/optimize', 8 | }, 9 | name = 'Gem TD Plus.w3x', 10 | }, 11 | 12 | source = { 13 | directory = 'src', 14 | include = { 15 | 'lib/patch/1.31.1', 16 | }, 17 | }, 18 | 19 | build = { 20 | 'share/environment', 21 | 'share/constants', 22 | 'share/objects', 23 | 'share/hide-buttons.lua', 24 | 'share/tooltips.lua', 25 | 26 | 'share/imports/import-directory.lua', 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /lib/gem/date.lua: -------------------------------------------------------------------------------- 1 | local Path = require('map.path') 2 | local Shell = require('map.shell') 3 | 4 | local date 5 | 6 | do 7 | local stdout = Path.temporary_path() 8 | 9 | local status = Shell.execute({ 10 | command = Shell.escape('git', 'show', '--no-patch', '--format=%ci'), 11 | stdout = Shell.escape(stdout), 12 | stderr = '&1', 13 | }) 14 | 15 | assert(status) 16 | 17 | local file = assert(io.open(stdout, 'rb')) 18 | date = file:read() 19 | file:close() 20 | 21 | os.remove(stdout) 22 | end 23 | 24 | return date 25 | -------------------------------------------------------------------------------- /lib/gem/deep_copy.lua: -------------------------------------------------------------------------------- 1 | local function deep_copy (old, ignore_metatable) 2 | local new 3 | 4 | if type(old) == 'table' then 5 | new = {} 6 | 7 | for key, value in pairs(old) do 8 | new[deep_copy(key)] = deep_copy(value) 9 | end 10 | 11 | if not ignore_metatable then 12 | setmetatable(new, deep_copy(getmetatable(old))) 13 | end 14 | else 15 | new = old 16 | end 17 | 18 | return new 19 | end 20 | 21 | return deep_copy 22 | -------------------------------------------------------------------------------- /lib/gem/id.lua: -------------------------------------------------------------------------------- 1 | -- Returns the `string` representation of an integer ID code (e.g. `A000`). 2 | return function (id) 3 | return string.pack('>I4', id) 4 | end 5 | -------------------------------------------------------------------------------- /lib/patch/1.27.0: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.27.1: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.0: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.1: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.2: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.3: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.4: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.28.5: -------------------------------------------------------------------------------- 1 | 1.26.0 -------------------------------------------------------------------------------- /lib/patch/1.29.1: -------------------------------------------------------------------------------- 1 | 1.29.0 -------------------------------------------------------------------------------- /lib/patch/1.29.2/blizzard.j: -------------------------------------------------------------------------------- 1 | ../1.29.0/blizzard.j -------------------------------------------------------------------------------- /lib/patch/1.30.1: -------------------------------------------------------------------------------- 1 | 1.30.0 -------------------------------------------------------------------------------- /lib/patch/1.30.2/blizzard.j: -------------------------------------------------------------------------------- 1 | ../1.30.0/blizzard.j -------------------------------------------------------------------------------- /lib/patch/1.30.3: -------------------------------------------------------------------------------- 1 | 1.30.2 -------------------------------------------------------------------------------- /lib/patch/1.30.4: -------------------------------------------------------------------------------- 1 | 1.30.2 -------------------------------------------------------------------------------- /lib/patch/1.31.1/blizzard.j: -------------------------------------------------------------------------------- 1 | ../1.31.0/blizzard.j -------------------------------------------------------------------------------- /lib/patch/1.31.1/common.ai: -------------------------------------------------------------------------------- 1 | ../1.31.0/common.ai -------------------------------------------------------------------------------- /lib/patch/README.md: -------------------------------------------------------------------------------- 1 | # Warcraft III Patch Scripts 2 | 3 | This is a collection of the `common.j` and `blizzard.j` from their respective 4 | patches. The intended purpose is reference only. Whitespace has been 5 | removed. Additional comments may be added. 6 | 7 | In short, **do not** use these with hosting bots (e.g. Ghost++). 8 | -------------------------------------------------------------------------------- /share/constants/gameplay/gem.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | local Misc = map.constants.gameplay.Misc 4 | 5 | -- Ally Trading Increment: 6 | Misc.TradingIncLarge = 0 -- Control Click 7 | Misc.TradingIncSmall = 0 -- Normal Click 8 | 9 | -- Build Status Display: 10 | Misc.DisplayBuildingStatus = 1 11 | 12 | -- Cancel Refund Factor: 13 | -- 14 | -- This is handled by 'Gem Placement'. No other structure is actually built 15 | -- using resources. 16 | Misc.ConstructionRefundRate = 0.0 -- Building Construction 17 | Misc.UpgradeRefundRate = 1.0 -- Building Upgrade 18 | 19 | -- Combat - Damage Bonus Table: 20 | -- 21 | -- Order: 22 | -- - Small (Red) 23 | -- - Medium (Blazed) 24 | -- - Large (White) 25 | -- - Fortified (Green) 26 | -- - Normal (Yellow) 27 | -- - Hero (Blue) 28 | -- - Divine (Bryvx) 29 | -- - Unarmored (Pink) 30 | 31 | Misc.DamageBonusChaos = -- Topaz 32 | '0.50,1.00,0.60,0.70,1.60,1.00,0.75,1.20' 33 | Misc.DamageBonusHero = -- Ruby 34 | '1.80,0.80,1.00,0.50,1.00,1.00,0.75,0.80' 35 | Misc.DamageBonusMagic = -- Water - Aquamarine / Opal 36 | '1.00,1.90,0.80,0.70,1.00,0.40,0.75,1.00' 37 | Misc.DamageBonusNormal = -- Diamond 38 | '1.20,1.00,1.60,1.00,0.60,1.00,0.75,0.20' 39 | Misc.DamageBonusPierce = -- Amethyst 40 | '0.80,0.80,0.80,0.80,0.80,0.80,0.75,1.75' 41 | Misc.DamageBonusSiege = -- Emerald 42 | '0.70,0.70,0.70,1.70,0.70,0.70,0.75,1.50' 43 | Misc.DamageBonusSpells = -- Sapphire 44 | '1.00,1.00,1.00,1.00,1.00,1.75,0.75,1.00' 45 | 46 | -- Hero Attributes: 47 | Misc.StrAttackBonus = 0.0 -- Attack Bonus per Primary Attribute 48 | Misc.AgiDefenseBonus = 0.04 -- Defense Bonus per Agility 49 | Misc.StrRegenBonus = 0.0 -- HP Regen Bonus per Strength 50 | Misc.StrHitPointBonus = 2000.0 -- HP Bonus per Strength 51 | Misc.IntManaBonus = 1.0 -- MP Bonus per Intelligence 52 | Misc.IntRegenBonus = 0.05 -- MP Regen Bonus per Intelligence 53 | 54 | -- Hero Maximum Level: 55 | Misc.MaxHeroLevel = 50 56 | 57 | -- Movement - Unit Speed: 58 | Misc.MaxUnitSpeed = 522.0 -- Maximum 59 | Misc.MinUnitSpeed = 220.0 -- Minimum 60 | 61 | -- Spells - Frost: 62 | Misc.FrostMoveSpeedDecrease = 0.2 -- Movement Speed Reduction 63 | 64 | -- Allow Multiple Bounces Per Hit 65 | Misc.AllowMultiBounce = 0 66 | -------------------------------------------------------------------------------- /share/constants/interface/upkeep.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local globals = map.globals 3 | 4 | map.settings.date = map.settings.date or require('lib.gem.date') 5 | 6 | -- # Upkeep 7 | 8 | local FrameDef = map.constants.interface.FrameDef 9 | 10 | local function color_link (text) 11 | return '|cff' .. globals.Color__LINK .. text .. '|r' 12 | end 13 | 14 | local white = '|cff' .. globals.Color__WHITE 15 | 16 | local function color_white (text) 17 | return white .. text .. '|r' 18 | end 19 | 20 | local function color_red (text) 21 | return '|cff' .. globals.Color__RED .. text .. '|r' 22 | end 23 | 24 | local function color_gold (text) 25 | return '|cff' .. globals.Color__GOLD .. text .. '|r' 26 | end 27 | 28 | local discord = color_link(globals.Gem__WEBSITE_DISCORD) 29 | local repository = color_link(globals.Gem__WEBSITE_REPOSITORY) 30 | local maintainer = color_red(globals.Gem__MAINTAINER) 31 | 32 | -- Text - General 'No Upkeep' 33 | -- 34 | -- We need to split this, or we cannot see build metadata in `1.29.0`. A tab 35 | -- character will not be rendered for players to see, but will be considered 36 | -- when breaking text over multiple lines. 37 | FrameDef.UPKEEP_NONE = color_gold(map.header.name:gsub('-', '\t-')) 38 | 39 | -- Text - General 'Gold Income Rate:' 40 | FrameDef.COLON_GOLD_INCOME_RATE = color_white('Maintained by ') 41 | .. maintainer 42 | .. white 43 | .. ' —' 44 | 45 | -- Text - General - 'Upkeep is determined...' 46 | FrameDef.RESOURCE_UBERTIP_UPKEEP = '- ' 47 | .. repository 48 | .. '|n' 49 | .. '- ' 50 | .. discord 51 | .. '|n|n' 52 | .. 'Released: ' 53 | .. map.settings.date 54 | 55 | -- Text - General - '|n%d-%d Food...' 56 | -- 57 | -- An empty string does not work here. This ensures that nothing is displayed 58 | -- by this field, which typically lists food ranges and associated income 59 | -- values. 60 | FrameDef.RESOURCE_UBERTIP_UPKEEP_INFO = '|r' 61 | -------------------------------------------------------------------------------- /share/environment/fix-games-list.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | -- Players listed in the `war3map.w3i` will be counted in the games list. 4 | -- Remove a few of them so that the maximum player count is `9`. Trying to 5 | -- target `8` will not reliably work. So, we go for `9`. 6 | map.information.players[9] = nil 7 | map.information.players[10] = nil 8 | map.information.players[11] = nil 9 | -------------------------------------------------------------------------------- /share/environment/header-loading-screen.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.settings.date = map.settings.date or require('lib.gem.date') 4 | 5 | local function color_red (text) 6 | return '|cff' .. map.globals.Color__RED .. text .. '|r' 7 | end 8 | 9 | local function color_link (text) 10 | return '|cff' .. map.globals.Color__LINK .. text .. '|r' 11 | end 12 | 13 | local maintainer = color_red(map.globals.Gem__MAINTAINER) 14 | local discord = color_link(map.globals.Gem__WEBSITE_DISCORD) 15 | local repository = color_link(map.globals.Gem__WEBSITE_REPOSITORY) 16 | 17 | map.information.map.description = string.format( 18 | [[ 19 | %s by %s|n- %s|n- %s|n|nReleased: %s]], 20 | map.globals.Gem__NAME_FULL, 21 | maintainer, 22 | repository, 23 | discord, 24 | map.settings.date 25 | ) 26 | 27 | map.information.loading.text = string.format( 28 | [[ 29 | An updated version of Gem Tower Defense, 30 | a map originally created by %s. 31 | 32 | Maintained by %s. 33 | 34 | For the latest news, to find other players, 35 | or to view the leaderboards, visit: 36 | 37 | - %s 38 | - %s 39 | 40 | Please report any bugs or errors encountered.]], 41 | color_red('Bryvx'), 42 | maintainer, 43 | repository, 44 | discord 45 | ) 46 | -------------------------------------------------------------------------------- /share/environment/lobby.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | -- Adjust the force names in 1.32. More W3I information is exposed in 4 | -- various places. 5 | map.information.forces[1].name = map.globals.Gem__NAME 6 | map.information.forces[2].name = ' ' 7 | 8 | map.information.forces[2] = nil 9 | 10 | -- Ensure that default player names are `Player #`. 11 | for index, player in ipairs(map.information.players) do 12 | player.name = string.format('Player %d', index) 13 | end 14 | 15 | map.information.map.author = map.globals.Gem__MAINTAINER 16 | -------------------------------------------------------------------------------- /share/environment/version.lua: -------------------------------------------------------------------------------- 1 | local Path = require('map.path') 2 | local Shell = require('map.shell') 3 | 4 | local map = ... 5 | 6 | local version 7 | 8 | do 9 | local stdout = Path.temporary_path() 10 | 11 | local status = Shell.execute({ 12 | command = Shell.escape('git', 'describe'), 13 | stdout = Shell.escape(stdout), 14 | stderr = '&1', 15 | }) 16 | 17 | assert(status) 18 | 19 | local file = assert(io.open(stdout, 'rb')) 20 | version = file:read():sub(2):gsub('%-g', '+g', 1) 21 | file:close() 22 | 23 | os.remove(stdout) 24 | end 25 | 26 | map.settings.version = version 27 | map.header.name = map.globals.Gem__NAME .. ' ' .. version 28 | map.information.map.name = map.header.name 29 | 30 | -- It is necessary to replace the '+' character in the file name as it will 31 | -- cause the map to not load into the lobby. 32 | map.settings.output.name = string.format( 33 | '%s %s.w3x', 34 | map.globals.Gem__NAME_PATH, 35 | version:gsub('%+', '_') 36 | ) 37 | 38 | map.information.loading.subtitle = map.globals.Gem__NAME_FULL 39 | map.information.loading.title = 'Version ' .. version 40 | 41 | map.strings[1] = map.header.name 42 | -------------------------------------------------------------------------------- /share/hide-buttons.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local abilities = { 5 | -- Lucky China Jade 6 | 'A02X', 7 | 8 | -- Rose Quartz Crystal 9 | 'A018', 10 | 11 | -- Uranium 235 12 | 'A016', 13 | 14 | -- Wraith 15 | 'A02V', 16 | 17 | -- Viper 18 | 'A074', 19 | 'A075', 20 | } 21 | 22 | local x = { 23 | type = 'integer', 24 | value = 0, 25 | } 26 | 27 | local y = { 28 | type = 'integer', 29 | value = -11, 30 | } 31 | 32 | for _, ability in ipairs(abilities) do 33 | local object = assert(objects[ability]) 34 | 35 | object.abpx = x 36 | object.abpy = y 37 | end 38 | -------------------------------------------------------------------------------- /share/imports/import-directory.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.imports['share/imports/map'] = true 4 | -------------------------------------------------------------------------------- /share/imports/map/FullScreen.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/FullScreen.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Blazed.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Blazed.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Blue.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Blue.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Bryvx.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Bryvx.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Green.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Green.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Pink.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Pink.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Red.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Red.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/White.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/White.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Armor/Yellow.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Armor/Yellow.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Amethyst.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Amethyst.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Diamond.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Diamond.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Emerald.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Emerald.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Ruby.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Ruby.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Sapphire.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Sapphire.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Topaz.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Topaz.blp -------------------------------------------------------------------------------- /share/imports/map/Gem/Attack/Water.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/Gem/Attack/Water.blp -------------------------------------------------------------------------------- /share/imports/map/LoadingScreen.mdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/LoadingScreen.mdx -------------------------------------------------------------------------------- /share/imports/map/ReplaceableTextures/CommandButtonsDisabled/DISPASOrbOfDarkness.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/ReplaceableTextures/CommandButtonsDisabled/DISPASOrbOfDarkness.blp -------------------------------------------------------------------------------- /share/imports/map/ReplaceableTextures/CommandButtonsDisabled/DISPASStaffOfNegation.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/ReplaceableTextures/CommandButtonsDisabled/DISPASStaffOfNegation.blp -------------------------------------------------------------------------------- /share/imports/map/ReplaceableTextures/PassiveButtons/PASBTNGems.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/ReplaceableTextures/PassiveButtons/PASBTNGems.blp -------------------------------------------------------------------------------- /share/imports/map/ReplaceableTextures/PassiveButtons/PASOrbOfDarkness.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/ReplaceableTextures/PassiveButtons/PASOrbOfDarkness.blp -------------------------------------------------------------------------------- /share/imports/map/ReplaceableTextures/PassiveButtons/PASStaffOfNegation.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/imports/map/ReplaceableTextures/PassiveButtons/PASStaffOfNegation.blp -------------------------------------------------------------------------------- /share/imports/map/Units/CommandFunc.txt: -------------------------------------------------------------------------------- 1 | [CmdMove] 2 | Art=CommandMove 3 | Buttonpos=0,0 4 | 5 | [CmdAttack] 6 | Art=CommandAttack 7 | Buttonpos=3,0 8 | 9 | [CmdAttackGround] 10 | Art=CommandAttackGround 11 | Buttonpos=2,0 12 | 13 | [CmdBuild] 14 | Art=CommandBasicStruct 15 | Buttonpos=0,2 16 | 17 | [CmdBuildHuman] 18 | Art=CommandBasicStructHuman 19 | Buttonpos=0,2 20 | 21 | [CmdBuildOrc] 22 | Art=CommandBasicStructOrc 23 | Buttonpos=0,2 24 | 25 | [CmdBuildNightElf] 26 | Art=CommandBasicStructNightElf 27 | Buttonpos=0,2 28 | 29 | [CmdBuildUndead] 30 | Art=CommandBasicStructUndead 31 | Buttonpos=0,2 32 | 33 | [CmdCancel] 34 | Art=CommandCancel 35 | ButtonPos=3,2 36 | 37 | [CmdCancelBuild] 38 | Art=CommandCancel 39 | ButtonPos=3,2 40 | 41 | [CmdCancelTrain] 42 | Art=CommandCancel 43 | ButtonPos=3,2 44 | 45 | [CmdCancelRevive] 46 | Art=CommandCancel 47 | ButtonPos=3,2 48 | 49 | [CmdHoldPos] 50 | Art=CommandHoldPosition 51 | Buttonpos=2,0 52 | 53 | [CmdPatrol] 54 | Art=CommandPatrol 55 | Buttonpos=0,1 56 | 57 | [CmdPurchase] 58 | Art=CommandPurchase 59 | Buttonpos=0,0 60 | 61 | [CmdRally] 62 | Art=CommandRally 63 | Buttonpos=3,1 64 | PlacementModel=UI\Feedback\RallyPoint\RallyPoint.mdl 65 | 66 | [CmdSelectSkill] 67 | Art=CommandNewSkill 68 | Buttonpos=3,1 69 | 70 | [CmdStop] 71 | Art=CommandStop 72 | Buttonpos=1,0 73 | 74 | //[CmdUnivAgi] 75 | //Art= 76 | //Buttonpos=2,0 77 | 78 | //[CmdUnivInt] 79 | //Art= 80 | //Buttonpos=1,0 81 | 82 | //[CmdUnivStr] 83 | //Art= 84 | //Buttonpos=0,0 85 | -------------------------------------------------------------------------------- /share/maps/Gem TD Plus.w3x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvs/gem/e073a589ea6b4ca26170d97feae8c5d6f7f0fb4a/share/maps/Gem TD Plus.w3x -------------------------------------------------------------------------------- /share/objects/air-slate.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Air Slate 5 | local unit = objects.n000 6 | 7 | -- ## Combats 8 | do 9 | -- Weapons Enabled 10 | unit.uaen.value = 2 11 | end 12 | -------------------------------------------------------------------------------- /share/objects/anti-stuck-cooldown.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Anti-Stuck Cooldown 5 | 6 | if objects['A02Y'] then 7 | local ability = objects['A02Y'] 8 | 9 | -- Data/Stats: Cooldown 10 | ability.acdn = { 11 | type = 'unreal', 12 | values = { 13 | [1] = 5.0, 14 | }, 15 | } 16 | end 17 | -------------------------------------------------------------------------------- /share/objects/black-opal.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | -- # Mystic Black Opal 4 | do 5 | local unit = map.objects.h02K 6 | 7 | -- ## Text 8 | do 9 | -- Hotkey 10 | unit.uhot = { 11 | type = 'string', 12 | value = 'R', 13 | } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /share/objects/bonus-armor.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local list = { 5 | GBAN = -4096, 6 | GBA0 = 1, 7 | GBA1 = 2, 8 | GBA2 = 4, 9 | GBA3 = 8, 10 | GBA4 = 16, 11 | GBA5 = 32, 12 | GBA6 = 64, 13 | GBA7 = 128, 14 | GBA8 = 256, 15 | GBA9 = 512, 16 | GBAA = 1024, 17 | GBAB = 2048, 18 | } 19 | 20 | -- # Bonus Armor Ability 21 | for id, armor in pairs(list) do 22 | local ability = { 23 | type = 'ability', 24 | base = 'AId1', 25 | } 26 | 27 | objects[id] = ability 28 | 29 | -- ## Data 30 | do 31 | ability.Idef = { 32 | data = 1, 33 | type = 'integer', 34 | values = { 35 | [1] = armor, 36 | }, 37 | } 38 | end 39 | 40 | -- ## Stats 41 | do 42 | ability.aite = { 43 | type = 'integer', 44 | value = 0, 45 | } 46 | end 47 | 48 | -- ## Text 49 | do 50 | -- Editor Suffix 51 | ability.ansf = { 52 | type = 'string', 53 | value = '(' .. armor .. ')', 54 | } 55 | 56 | -- Name 57 | ability.anam = { 58 | type = 'string', 59 | value = 'Bonus Armor', 60 | } 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /share/objects/buff-icons.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | objects.B002.fart.value = 5 | 'ReplaceableTextures\\CommandButtons\\BTNFeedBack.blp' 6 | objects.B00A.fart.value = 7 | 'ReplaceableTextures\\CommandButtons\\BTNReplenishHealth.blp' 8 | objects.B00J.fart.value = 9 | 'ReplaceableTextures\\CommandButtons\\BTNMagicImmunity.blp' 10 | -------------------------------------------------------------------------------- /share/objects/change-topaz-base.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Change Topaz Base 5 | 6 | local topazes = { 7 | 'e000', -- Chipped 8 | 'e001', -- Flawed 9 | 'e002', -- Normal 10 | 'e003', -- Flawless 11 | 'e004', -- Perfect 12 | 'e005', -- Great 13 | } 14 | 15 | for index, id in ipairs(topazes) do 16 | local topaz = objects[id] 17 | 18 | -- Ensure that the unit base is Guard Tower. The old Naisha base (i.e. 19 | -- `ensh`) could crash the game in certain instances. 20 | topaz.base = 'hgtw' 21 | 22 | -- ## Art 23 | 24 | -- Projectile Impact - Z 25 | topaz.uimz = { 26 | type = 'unreal', 27 | value = 60, 28 | } 29 | 30 | -- Projectile Launch - Z 31 | topaz.ulpz = { 32 | type = 'unreal', 33 | value = 60, 34 | } 35 | 36 | topaz.ushb = { 37 | type = 'string', 38 | value = '', 39 | } 40 | 41 | -- ## Combat 42 | local range = 500 43 | 44 | if index == 5 then -- Perfect 45 | range = 600 46 | elseif index == 6 then -- Great 47 | range = 700 48 | end 49 | 50 | -- Acquisition Range 51 | topaz.uacq = { 52 | type = 'unreal', 53 | value = range, 54 | } 55 | 56 | -- ### Combat - Attack 1 57 | 58 | -- Animation Backswing Point 59 | topaz.ubs1 = { 60 | type = 'unreal', 61 | value = 0.54, 62 | } 63 | 64 | -- Animation Damage Point 65 | topaz.udp1 = { 66 | type = 'unreal', 67 | value = 0.46, 68 | } 69 | 70 | -- Projectile Arc 71 | topaz.uma1 = { 72 | type = 'unreal', 73 | value = 0.1, 74 | } 75 | 76 | -- Projectile Speed 77 | topaz.ua1z = { 78 | type = 'integer', 79 | value = 900, 80 | } 81 | 82 | -- Range 83 | topaz.ua1r = { 84 | type = 'integer', 85 | value = range, 86 | } 87 | end 88 | -------------------------------------------------------------------------------- /share/objects/cheats.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | local cheats = { 8 | unit = { 9 | id = id(globals.Cheats___UNIT_ID), 10 | base = id(globals.Cheats___UNIT_BASE_ID), 11 | }, 12 | 13 | mana = { 14 | id = id(globals.Cheats___MANA_ID), 15 | base = id(globals.Cheats___MANA_BASE_ID), 16 | }, 17 | } 18 | 19 | local suffix = { 20 | type = 'string', 21 | value = '(Cheats)', 22 | } 23 | 24 | -- # Cheats - Unit 25 | do 26 | objects[cheats.unit.id] = { 27 | type = 'unit', 28 | base = cheats.unit.base, 29 | } 30 | 31 | local unit = objects[cheats.unit.id] 32 | 33 | -- ## Techtree 34 | do 35 | -- Units Trained 36 | unit.utra = { 37 | type = 'string', 38 | value = cheats.unit.id, 39 | } 40 | end 41 | 42 | -- ## Text 43 | do 44 | -- Editor Suffix 45 | unit.unsf = suffix 46 | 47 | -- Name 48 | unit.unam = { 49 | type = 'string', 50 | value = 'Unit', 51 | } 52 | end 53 | end 54 | 55 | -- # Cheats - No Mana 56 | do 57 | objects[cheats.mana.id] = { 58 | type = 'ability', 59 | base = cheats.mana.base, 60 | } 61 | 62 | local ability = objects[cheats.mana.id] 63 | 64 | -- ## Text 65 | do 66 | -- Editor Suffix 67 | ability.ansf = suffix 68 | 69 | -- Name 70 | ability.anam = { 71 | type = 'string', 72 | value = 'No Mana', 73 | } 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /share/objects/combine-special-button.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Combination Button 5 | 6 | objects.A00R.atp1.values = { 7 | [1] = 'Combine Special', 8 | } 9 | objects.A10R = objects.A00R 10 | -------------------------------------------------------------------------------- /share/objects/difficulty-armor-changes.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Difficulty Armor Changes 5 | 6 | local units = { 7 | [1] = { 'h00D', 12 }, 8 | [2] = { 'h00Z', 12 }, 9 | [3] = { 'h010', 12 }, 10 | [4] = { 'h011', 12 }, 11 | [5] = { 'h012', 12 }, 12 | [6] = { 'h013', 12 }, 13 | [7] = { 'h01C', 12 }, 14 | [8] = { 'h01D', 12 }, 15 | [9] = { 'h01E', 12 }, 16 | [10] = { 'h01F', 15 }, 17 | [11] = { 'h01G', 15 }, 18 | [12] = { 'h01H', 13 }, 19 | [13] = { 'h01I', 15 }, 20 | [14] = { 'h01J', 15 }, 21 | [15] = { 'h01K', 15 }, 22 | [16] = { 'h01L', 13 }, 23 | [17] = { 'h02I', 15 }, 24 | [18] = { 'h037', 15 }, 25 | [19] = { 'h038', 15 }, 26 | [20] = { 'h01R', 13 }, 27 | [21] = { 'h039', 19 }, 28 | [22] = { 'h03A', 19 }, 29 | [23] = { 'h03B', 19 }, 30 | [24] = { 'h01X', 13 }, 31 | [25] = { 'h03C', 19 }, 32 | [26] = { 'h03D', 19 }, 33 | [27] = { 'h03E', 19 }, 34 | [28] = { 'h021', 14 }, 35 | [29] = { 'h03F', 19 }, 36 | [30] = { 'h03G', 23 }, 37 | [31] = { 'h03H', 23 }, 38 | [32] = { 'h025', 14 }, 39 | [33] = { 'h03I', 23 }, 40 | [34] = { 'h03J', 23 }, 41 | [35] = { 'h03K', 23 }, 42 | [36] = { 'h02B', 14 }, 43 | [37] = { 'h03L', 23 }, 44 | [38] = { 'h03M', 23 }, 45 | [39] = { 'h03N', 23 }, 46 | [40] = { 'h02F', 14 }, 47 | [41] = { 'h03O', 30 }, 48 | [42] = { 'h03P', 34 }, 49 | [43] = { 'h04K', 35 }, 50 | [44] = { 'h04I', 14 }, 51 | [45] = { 'h04L', 35 }, 52 | [46] = { 'h04M', 35 }, 53 | [47] = { 'h04N', 35 }, 54 | [48] = { 'h04J', 15 }, 55 | [49] = { 'h04O', 35 }, 56 | [50] = { 'h04P', 35 }, 57 | [51] = { 'H04B', 40 }, 58 | } 59 | 60 | for level, pair in ipairs(units) do 61 | local id = pair[1] 62 | local armor = pair[2] 63 | 64 | local unit = objects[id] 65 | 66 | if unit then 67 | -- Combat: Defense Base 68 | unit.udef = { 69 | type = 'integer', 70 | value = armor, 71 | } 72 | end 73 | 74 | if level % 4 == 0 or (40 <= level and level < 50) then 75 | unit.uhpm.value = unit.uhpm.value * 1.2 76 | elseif level == 50 then 77 | unit.uhpm.value = 85000 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /share/objects/dummy-caster.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Dummy Caster 5 | 6 | -- This base object is used by both Wurst and Nestharus. 7 | objects['DUCA'] = { 8 | type = 'unit', 9 | base = 'nfr2', 10 | 11 | -- ## Abilities 12 | 13 | -- Normal 14 | uabi = { 15 | type = 'string', 16 | value = 'Aloc,Avul', 17 | }, 18 | 19 | -- ## Art 20 | 21 | -- Animation - Blend Time 22 | uble = { 23 | type = 'real', 24 | value = 0, 25 | }, 26 | 27 | -- Animation - Cast Backswing 28 | ucbs = { 29 | type = 'unreal', 30 | value = 0, 31 | }, 32 | 33 | -- Animation - Cast Point 34 | ucpt = { 35 | type = 'unreal', 36 | value = 0, 37 | }, 38 | 39 | -- Ground Texture 40 | uubs = { 41 | type = 'string', 42 | value = '', 43 | }, 44 | 45 | -- Maximum Pitch Angle (Degrees) 46 | umxp = { 47 | type = 'real', 48 | value = 0, 49 | }, 50 | 51 | -- Minimum Pitch Angle (Degrees) 52 | umxr = { 53 | type = 'real', 54 | value = 0, 55 | }, 56 | 57 | -- Scaling Value 58 | usca = { 59 | type = 'real', 60 | value = 0.01, 61 | }, 62 | 63 | -- Shadow Texture (Building) 64 | ushb = { 65 | type = 'string', 66 | value = '', 67 | }, 68 | 69 | -- ## Editor 70 | 71 | -- Placeable In Editor 72 | uine = { 73 | type = 'integer', 74 | value = 0, 75 | }, 76 | 77 | -- ## Pathing 78 | 79 | -- Collision Size 80 | ucol = { 81 | type = 'unreal', 82 | value = 0, 83 | }, 84 | 85 | -- Pathing Map 86 | upat = { 87 | type = 'string', 88 | value = '', 89 | }, 90 | 91 | -- ## Sound 92 | 93 | -- Unit Sound Set 94 | usnd = { 95 | type = 'string', 96 | value = '', 97 | }, 98 | 99 | -- ## Stats 100 | 101 | -- Food Cost 102 | ufoo = { 103 | type = 'integer', 104 | value = 0, 105 | }, 106 | 107 | -- Hide Minimap Display 108 | uhom = { 109 | type = 'integer', 110 | value = 1, 111 | }, 112 | 113 | -- ## Text 114 | 115 | -- Editor Suffix 116 | unsf = { 117 | type = 'string', 118 | value = '', 119 | }, 120 | 121 | -- Name 122 | unam = { 123 | type = 'string', 124 | value = 'Dummy Caster', 125 | }, 126 | } 127 | -------------------------------------------------------------------------------- /share/objects/emerald-poison-kill.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local list = { 5 | A002 = 2, 6 | A003 = 4, 7 | A00B = 8, 8 | A00C = 16, 9 | A00D = 40, 10 | A01J = 100, 11 | } 12 | 13 | for id, damage in pairs(list) do 14 | local ability = objects[id] 15 | 16 | -- Stats - Stacking Type 17 | ability.Spo4 = { 18 | data = 4, 19 | type = 'integer', 20 | values = { 21 | [1] = 9, 22 | }, 23 | } 24 | 25 | ability.adur = { 26 | type = 'unreal', 27 | values = { 28 | [1] = 6, 29 | }, 30 | } 31 | 32 | ability.Spo1 = { 33 | data = 1, 34 | type = 'unreal', 35 | values = { 36 | [1] = damage, 37 | }, 38 | } 39 | 40 | ability.Spo2 = { 41 | data = 2, 42 | type = 'unreal', 43 | values = { 44 | [1] = 0.2, 45 | }, 46 | } 47 | 48 | -- Stats - Duration - Hero 49 | ability.ahdu = ability.adur 50 | end 51 | -------------------------------------------------------------------------------- /share/objects/fix-lumber-costs.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Fix Lumber Costs 5 | -- 6 | -- This is simply a precaution, as code that previously refunded lumber when 7 | -- construction was canceled was removed. The code ensured that only the 8 | -- unit used for gem placement was ever considered. The new method, which 9 | -- uses a gameplay constant (`Cancel Building Factor - Building 10 | -- Construction`) is building agnostic. Hence, the need to ensure that other 11 | -- buildings do not have a lumber cost. To be fair, this is probably not 12 | -- needed. 13 | 14 | local list = { 15 | 'h005', -- Chipped Ruby 16 | 'h00C', -- Flawed Ruby 17 | 'h00M', -- Ruby 18 | 'h00R', -- Flawless Ruby 19 | 'h00T', -- Perfect Ruby 20 | 'h02Y', -- Great Ruby 21 | 'h014', -- Yellow Sapphire 22 | 'h016', -- Star Ruby 23 | 'h01A', -- Silver 24 | 'h01B', -- Gold 25 | 'h01O', -- Blood Stone 26 | } 27 | 28 | for _, id in ipairs(list) do 29 | local unit = objects[id] 30 | 31 | if unit then 32 | unit.ulum = { 33 | type = 'integer', 34 | value = 0, 35 | } 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /share/objects/gold-mine-buttons.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Once the upgrades are maximized, special versions of the buttons are used. 5 | -- However, due to both being based upon Moon Glaive, graphical issues are 6 | -- encountered. Basing them upon Evasion seems to work better. 7 | local buttons = { 8 | -- Gem Quality 9 | { 10 | id = 'A00E', 11 | icon = 'ReplaceableTextures\\PassiveButtons\\PASOrbOfDarkness.blp', 12 | }, 13 | } 14 | 15 | -- Deleting an object does not seem possible. However, it appears an object 16 | -- can be overwritten, preserving existing information. We switch to using 17 | -- Evasion as a base. 18 | for _, button in ipairs(buttons) do 19 | local ability = objects[button.id] 20 | 21 | if ability then 22 | ability.base = 'ACev' 23 | 24 | -- # Art 25 | 26 | -- Icon - Normal 27 | ability.aart = { 28 | type = 'string', 29 | value = button.icon, 30 | } 31 | 32 | -- # Data/Stats 33 | 34 | -- Chance to Evade 35 | ability.Eev1 = { 36 | data = 1, 37 | type = 'unreal', 38 | values = { 39 | [1] = 0, 40 | }, 41 | } 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /share/objects/great-amethyst.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.objects.h02X.uabi.value = map.objects.h02X.uabi.value:gsub(',A01I', '') 4 | -------------------------------------------------------------------------------- /share/objects/jade.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local list = { 5 | A00J = 15, 6 | A014 = 30, 7 | A00P = 60, 8 | } 9 | 10 | for id, damage in pairs(list) do 11 | local ability = objects[id] 12 | 13 | ability.adur = { 14 | type = 'unreal', 15 | values = { 16 | [1] = 4, 17 | }, 18 | } 19 | 20 | -- Stats - Duration - Hero 21 | ability.ahdu = ability.adur 22 | 23 | ability.Spo1 = { 24 | data = 1, 25 | type = 'unreal', 26 | values = { 27 | [1] = damage, 28 | }, 29 | } 30 | 31 | ability.Spo2 = { 32 | data = 2, 33 | type = 'unreal', 34 | values = { 35 | [1] = 0.2, 36 | }, 37 | } 38 | 39 | -- Stats - Stacking Type 40 | ability.Spo4 = { 41 | data = 4, 42 | type = 'integer', 43 | values = { 44 | [1] = 9, 45 | }, 46 | } 47 | end 48 | -------------------------------------------------------------------------------- /share/objects/kill-bonus-remove-brilliance-aura.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Kill Bonus: Remove Brilliance Aura 5 | -- 6 | -- It seems that the second tier of kill bonuses is based upon Brilliance 7 | -- Aura. It also seems that the mana regenation effect may be applied to the 8 | -- unit. It is my understanding that the only kill bonus should be damage. 9 | 10 | local list = { 11 | 'A01Z', -- 04 12 | 'A01P', -- 05 13 | 'A022', -- 06 14 | 'A023', -- 07 15 | 'A024', -- 08 16 | 'A021', -- 09 17 | 'A020', -- 10 18 | 'A01Y', -- 11 19 | 'A025', -- 25 20 | } 21 | 22 | for _, id in ipairs(list) do 23 | local unit = objects[id] 24 | 25 | if unit then 26 | -- Targets Allowed 27 | unit.atar = { 28 | type = 'string', 29 | values = { 30 | [1] = 'none', 31 | }, 32 | } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /share/objects/kill-bonus-remove-spell-immunity.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Kill Bonus: Remove Spell Immunity 5 | -- 6 | -- The third tier of kill bonuses is based upon Spell Immunity. This presents 7 | -- issues with the disarm system, as well as being able to swap. Other issues 8 | -- may exist that are not recognized. 9 | 10 | local abilities = { 11 | { 'A026', 7, 'Honored', 1 }, 12 | { 'A027', 8, 'Treasured', 2 }, 13 | { 'A028', 9, 'Loved', 3 }, 14 | { 'A029', 10, 'Preferred', 3 }, 15 | { 'A02A', 11, 'Idolized', 3 }, 16 | { 'A02B', 12, 'Worshipped', 3 }, 17 | } 18 | 19 | for _, ability in ipairs(abilities) do 20 | objects[ability[1]] = { 21 | type = 'ability', 22 | base = 'ACac', 23 | 24 | -- # Art 25 | 26 | -- Icon - Normal 27 | aart = { 28 | type = 'string', 29 | value = 'ReplaceableTextures\\CommandButtons\\BTN3M' 30 | .. ability[4] 31 | .. '.blp', 32 | }, 33 | 34 | -- Button Position - Normal (X) 35 | abpx = { 36 | type = 'integer', 37 | value = 2, 38 | }, 39 | 40 | -- Button Position - Normal (Y) 41 | abpy = { 42 | type = 'integer', 43 | value = 1, 44 | }, 45 | 46 | -- # Data/Stats 47 | 48 | -- Targets Allowed 49 | atar = { 50 | type = 'string', 51 | values = { 52 | [1] = 'none', 53 | }, 54 | }, 55 | 56 | -- # Text 57 | 58 | -- Name 59 | anam = { 60 | type = 'string', 61 | value = 'Award ' .. ability[2] .. ' xx', 62 | }, 63 | 64 | -- Tooltip - Normal 65 | atp1 = { 66 | type = 'string', 67 | values = { 68 | [1] = '|cffff00ff' .. ability[3] .. '|r', 69 | }, 70 | }, 71 | 72 | -- Tooltip - Normal - Extended 73 | aub1 = { 74 | type = 'string', 75 | values = { 76 | [1] = '', 77 | }, 78 | }, 79 | } 80 | end 81 | -------------------------------------------------------------------------------- /share/objects/make-slates-repairable.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Make Slates Repairable 5 | 6 | local slates = { 7 | 'n000', -- Air 8 | 'n002', -- Hold 9 | 'n003', -- Ancient 10 | 11 | 'n001', -- Slow 12 | 'n004', -- Opal Vein 13 | 'n005', -- Wraith 14 | 15 | 'n008', -- Poison 16 | 'n009', -- Spell 17 | 'n00A', -- Elder 18 | 19 | 'n00C', -- Damage 20 | 'n00E', -- Range 21 | 'n00F', -- Viper 22 | } 23 | 24 | for _, id in ipairs(slates) do 25 | local unit = objects[id] 26 | 27 | if unit then 28 | unit.utyp = { 29 | type = 'string', 30 | value = 'mechanical,standon,ancient', 31 | } 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /share/objects/monster-names.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | objects.h03G.unam.value = 'Extreme Ogre Lord' 5 | -------------------------------------------------------------------------------- /share/objects/nerf-wraith.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ability = objects.A02V 5 | 6 | ability.Nic2.values = { 500 } 7 | ability.Nic3.values = { 250 } 8 | ability.Nic4.values = { 250 } 9 | ability.Nic5.values = { 750 } 10 | ability.aub1.values = { 11 | 'Covers a unit in living flames. If a unit dies while under this ' 12 | .. 'effect, it is incinerated, causing damage to all ' 13 | .. 'nearby units within range. Units outside the primary ' 14 | .. 'explosion, up to range, will receive ' 15 | .. 'damage.', 16 | } 17 | -------------------------------------------------------------------------------- /share/objects/normal.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | local normals = { 8 | id(globals.Gem_Gems__AMETHYST_NORMAL), 9 | id(globals.Gem_Gems__AQUAMARINE_NORMAL), 10 | id(globals.Gem_Gems__DIAMOND_NORMAL), 11 | id(globals.Gem_Gems__EMERALD_NORMAL), 12 | id(globals.Gem_Gems__OPAL_NORMAL), 13 | id(globals.Gem_Gems__RUBY_NORMAL), 14 | id(globals.Gem_Gems__SAPPHIRE_NORMAL), 15 | id(globals.Gem_Gems__TOPAZ_NORMAL), 16 | } 17 | 18 | for _, normal in ipairs(normals) do 19 | local object = objects[normal] 20 | object.unam.value = 'Normal ' .. object.unam.value 21 | end 22 | -------------------------------------------------------------------------------- /share/objects/paraiba.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | -- Properly set the hero duration on Paraiba chills. 4 | map.objects.A03J.ahdu = map.objects.A03J.adur 5 | map.objects.A03N.ahdu = map.objects.A03N.adur 6 | -------------------------------------------------------------------------------- /share/objects/pink-diamond.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | objects.A017.Ocr2.values = { 15 } 5 | objects.A00I.Ocr2.values = { 9 } 6 | -------------------------------------------------------------------------------- /share/objects/pink.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | objects.A017.Ocr2.value = 15 5 | objects.A00I.Ocr2.value = 9 6 | -------------------------------------------------------------------------------- /share/objects/place-gem.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.objects.h006.utip.value = 'Place random gem' 4 | -------------------------------------------------------------------------------- /share/objects/range-check.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | -- # Range Check 4 | do 5 | local ability = map.objects.A03B 6 | 7 | -- ## Text 8 | do 9 | -- Hotkey - Normal 10 | ability.ahky.value = 'C' 11 | 12 | -- Tooltip - Normal 13 | ability.atp1.values[1] = 'Range Check' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /share/objects/remove-rock.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.objects.A008.atp1.values = { 4 | [1] = 'Remove Rock', 5 | } 6 | -------------------------------------------------------------------------------- /share/objects/ruby-splash.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | local ids = { 4 | 'h005', 5 | 'h00C', 6 | 'h00M', 7 | 'h00R', 8 | 'h00T', 9 | } 10 | 11 | -- Align splash range for all Rubies. 12 | for _, id in ipairs(ids) do 13 | map.objects[id].ua1f.value = 200 14 | map.objects[id].ua1h.value = 220 15 | map.objects[id].ua1q.value = 240 16 | end 17 | -------------------------------------------------------------------------------- /share/objects/selection.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Keep 5 | do 6 | local ability = objects['A009'] 7 | 8 | -- ## Text 9 | do 10 | -- Hotkey - Normal 11 | ability.ahky = { 12 | type = 'string', 13 | value = 'Z', 14 | } 15 | 16 | -- Tooltip - Normal 17 | ability.atp1 = { 18 | type = 'string', 19 | values = { 20 | [1] = 'Keep', 21 | }, 22 | } 23 | end 24 | end 25 | 26 | -- Downgrade 27 | do 28 | local ability = objects['A02G'] 29 | 30 | -- ## Text 31 | do 32 | -- Hotkey - Normal 33 | ability.ahky = { 34 | type = 'string', 35 | value = 'X', 36 | } 37 | 38 | -- Tooltip - Normal 39 | ability.atp1 = { 40 | type = 'string', 41 | values = { 42 | [1] = 'Downgrade', 43 | }, 44 | } 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /share/objects/selection/slate.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local globals = map.globals 3 | local objects = map.objects 4 | 5 | local id = require('lib.gem.id') 6 | 7 | local slate = { 8 | keep = id(globals.Gem_Selection_Slate__KEEP_ID), 9 | combine = id(globals.Gem_Selection_Slate__COMBINE_ID), 10 | } 11 | 12 | -- Remove objects. 13 | objects['A03M'] = nil 14 | 15 | -- # Gem Selection Slate Keep 16 | objects[slate.keep] = { 17 | type = 'ability', 18 | base = 'AAns', 19 | 20 | -- ## Art 21 | 22 | -- Button Position - Normal (X) 23 | abpx = { 24 | type = 'integer', 25 | value = 1, 26 | }, 27 | 28 | -- Button Position - Normal (Y) 29 | abpy = { 30 | type = 'integer', 31 | value = 1, 32 | }, 33 | 34 | -- Icon - Normal 35 | aart = { 36 | type = 'string', 37 | value = 'ReplaceableTextures\\CommandButtons\\BTNReplenishHealth.blp', 38 | }, 39 | 40 | -- ## Data 41 | 42 | -- Base Order ID 43 | Ans5 = { 44 | data = 5, 45 | type = 'string', 46 | values = { 47 | [1] = globals.Gem_Selection_Slate___KEEP_ORDER, 48 | }, 49 | }, 50 | 51 | -- Gold Cost 52 | Ndt1 = { 53 | data = 1, 54 | type = 'integer', 55 | values = { 56 | [1] = 0, 57 | }, 58 | }, 59 | 60 | -- ## Text 61 | 62 | -- Editor Suffix 63 | ansf = { 64 | type = 'string', 65 | value = '(Selection)', 66 | }, 67 | 68 | -- Hotkey - Normal 69 | ahky = { 70 | type = 'string', 71 | value = ' ', 72 | }, 73 | 74 | -- Name 75 | anam = { 76 | type = 'string', 77 | value = 'Keep Slate', 78 | }, 79 | 80 | -- Tooltip - Normal 81 | atp1 = { 82 | type = 'string', 83 | values = { 84 | [1] = 'Keep Slate', 85 | }, 86 | }, 87 | 88 | -- Tooltip - Normal - Extended 89 | aub1 = { 90 | type = 'string', 91 | values = { 92 | [1] = '', 93 | }, 94 | }, 95 | } 96 | 97 | -- # Gem Selection Slate Combine 98 | objects[slate.combine] = { 99 | type = 'ability', 100 | base = 'AAns', 101 | 102 | -- ## Art 103 | 104 | -- Button Position - Normal (X) 105 | abpx = { 106 | type = 'integer', 107 | value = 2, 108 | }, 109 | 110 | -- Button Position - Normal (Y) 111 | abpy = { 112 | type = 'integer', 113 | value = 1, 114 | }, 115 | 116 | -- Icon - Normal 117 | aart = { 118 | type = 'string', 119 | value = 'ReplaceableTextures\\CommandButtons\\BTNReplenishMana.blp', 120 | }, 121 | 122 | -- ## Data 123 | 124 | -- Base Order ID 125 | Ans5 = { 126 | data = 5, 127 | type = 'string', 128 | values = { 129 | [1] = globals.Gem_Selection_Slate___COMBINE_ORDER, 130 | }, 131 | }, 132 | 133 | -- Gold Cost 134 | Ndt1 = { 135 | data = 1, 136 | type = 'integer', 137 | values = { 138 | [1] = 0, 139 | }, 140 | }, 141 | 142 | -- ## Text 143 | 144 | -- Editor Suffix 145 | ansf = { 146 | type = 'string', 147 | value = '(Selection)', 148 | }, 149 | 150 | -- Hotkey - Normal 151 | ahky = { 152 | type = 'string', 153 | value = ' ', 154 | }, 155 | 156 | -- Name 157 | anam = { 158 | type = 'string', 159 | value = 'Keep Slate Combination', 160 | }, 161 | 162 | -- Tooltip - Normal 163 | atp1 = { 164 | type = 'string', 165 | values = { 166 | [1] = 'Keep Slate Combination', 167 | }, 168 | }, 169 | 170 | -- Tooltip - Normal - Extended 171 | aub1 = { 172 | type = 'string', 173 | values = { 174 | [1] = '', 175 | }, 176 | }, 177 | } 178 | -------------------------------------------------------------------------------- /share/objects/slate/ancient.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Armor Reduction Ability 5 | do 6 | local ability = objects.A02I 7 | 8 | -- ## Data 9 | do 10 | -- Armor Bonus 11 | ability.Had1.values = { 12 | [1] = 0, 13 | } 14 | end 15 | 16 | -- ## Stats 17 | do 18 | -- Area of Effect 19 | ability.aare = nil 20 | end 21 | end 22 | 23 | -- # Armor Reduction Buff 24 | do 25 | local buff = objects.B008 26 | 27 | buff.ftip.value = 'Ancient Slate' 28 | buff.fube.value = 'This unit\'s armor has been reduced' 29 | .. ' by an Ancient Slate.' 30 | end 31 | -------------------------------------------------------------------------------- /share/objects/slate/elder.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Elder Armor Debuff 5 | do 6 | local debuff = objects['A05W'] 7 | 8 | local duration = {} 9 | local armor = {} 10 | 11 | for level = 1, 11 do 12 | duration[level] = 25.0 13 | armor[level] = -7 14 | end 15 | 16 | -- ## Data 17 | 18 | -- Armor Bonus 19 | debuff.Ufa2.values = armor 20 | 21 | -- Armor Duration 22 | debuff.Ufa1.values = duration 23 | 24 | -- ## Stats 25 | 26 | -- Duration - Hero 27 | debuff.ahdu.values = duration 28 | 29 | -- Duration - Normal 30 | debuff.adur.values = duration 31 | end 32 | 33 | -- # Elder Information 34 | do 35 | local info = objects['A061'] 36 | 37 | -- ## Text 38 | 39 | -- Tooltip - Normal - Extended 40 | for level = 1, 11 do 41 | info.aub1.values[level] = string.format( 42 | [[ 43 | Chance to cast per attack: 44 | - 5%% Frost Nova ( Damage) 45 | - 5%% Fan of Knives ( Damage) 46 | - 7%% Armor Reduction ( Armor) 47 | - 5%% Shockwave ( Damage) 48 | - 5%% Forked Lightning ( Damage) 49 | - 8%% Poison Shot ( Damage / 2 seconds)]], 50 | level, 51 | level, 52 | level, 53 | level, 54 | level, 55 | level 56 | ) 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /share/objects/slate/poison.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | 3 | map.objects.A05M.alev = { 4 | type = 'integer', 5 | value = 11, 6 | } 7 | 8 | -- Set the initial hit to equal that of the damage over time. 9 | map.objects.A05N.Esh5.values = map.objects.A05N.Esh1.values 10 | -------------------------------------------------------------------------------- /share/objects/slate/spell.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Spell Information 5 | do 6 | local info = objects['A05P'] 7 | 8 | -- ## Text 9 | 10 | -- Tooltip - Normal - Extended 11 | info.aub1.values = { 12 | [1] = 'Chance to cast per attack:|n' 13 | .. '- 5% Frost Nova (100)|n' 14 | .. '- 5% Fan of Knives (80)|n' 15 | .. '- 5% Lightning (85)|n' 16 | .. '- 5% Carrion Swarm (125)|n' 17 | .. '- 5% Armor Reduction (5)', 18 | } 19 | end 20 | -------------------------------------------------------------------------------- /share/objects/slate/viper.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ids = { 5 | immolation = 'A075', 6 | aura = 'A076', 7 | } 8 | 9 | -- # Viper Slate Immolation 10 | do 11 | local ability = { 12 | type = 'ability', 13 | base = 'ACev', 14 | } 15 | objects[ids.immolation] = ability 16 | 17 | -- ## Art 18 | do 19 | -- Button Position - Normal (X) 20 | ability.abpx = { 21 | type = 'integer', 22 | value = 2, 23 | } 24 | 25 | -- Button Position - Normal (Y) 26 | ability.abpy = { 27 | type = 'integer', 28 | value = 1, 29 | } 30 | 31 | -- Icon - Normal 32 | ability.aart = { 33 | type = 'string', 34 | value = 'ReplaceableTextures\\PassiveButtons\\PASBTNStatUp.blp', 35 | } 36 | end 37 | 38 | -- ## Data 39 | do 40 | -- Chance to Evade 41 | ability.Eev1 = { 42 | data = 1, 43 | type = 'unreal', 44 | values = { 45 | [1] = 0, 46 | }, 47 | } 48 | end 49 | 50 | -- ## Stats 51 | do 52 | -- Area of Effect 53 | ability.aare = { 54 | type = 'unreal', 55 | values = { 56 | [1] = 400, 57 | }, 58 | } 59 | 60 | -- Cooldown 61 | ability.acdn = { 62 | type = 'unreal', 63 | values = {}, 64 | } 65 | 66 | for level = 1, 11 do 67 | ability.acdn.values[level] = 50 * (1 + 0.1 * (level - 1)) 68 | end 69 | 70 | -- Levels 71 | ability.alev = { 72 | type = 'integer', 73 | value = 11, 74 | } 75 | 76 | -- Race 77 | ability.arac = { 78 | type = 'string', 79 | value = 'human', 80 | } 81 | end 82 | 83 | -- ## Text 84 | do 85 | -- Editor Suffix 86 | ability.ansf = { 87 | type = 'string', 88 | value = '(Viper Slate)', 89 | } 90 | 91 | -- Name 92 | ability.anam = { 93 | type = 'string', 94 | value = 'Abilities II', 95 | } 96 | 97 | -- Tooltip - Normal 98 | ability.atp1 = { 99 | type = 'string', 100 | values = { 101 | [1] = '|cff33ff33Viper Slate Abilities 2|r', 102 | }, 103 | } 104 | 105 | -- Tooltip - Normal - Extended 106 | ability.aub1 = { 107 | type = 'string', 108 | values = {}, 109 | } 110 | 111 | local text = 'Enemies within <%s,Area1> range will receive' 112 | .. ' <%s,Cool%d> spell damage per second.' 113 | 114 | for level = 1, 11 do 115 | ability.aub1.values[level] = 116 | string.format(text, ids.immolation, ids.immolation, level) 117 | end 118 | end 119 | end 120 | 121 | -- # Viper Slate Aura 122 | do 123 | local ability = objects[ids.aura] 124 | 125 | -- ## Data 126 | do 127 | -- Attack Damage Increase 128 | for level = 1, 11 do 129 | ability.Cac1.values[level] = 0.10 + 0.03 * (level - 1) 130 | end 131 | end 132 | 133 | -- ## Text 134 | do 135 | -- Tooltip - Normal - Extended 136 | local text = 'Grants a <%s,DataA%d,%%>%% increased damage aura to ' 137 | .. 'friendly structures within <%s,Area%d> range.' 138 | 139 | for level = 1, 11 do 140 | ability.aub1.values[level] = 141 | string.format(text, ids.aura, level, ids.aura, level) 142 | end 143 | end 144 | end 145 | -------------------------------------------------------------------------------- /share/objects/specials/blood-stone/02-ancient-blood-stone.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Ancient Blood Stone Information 5 | do 6 | local ability = objects['A019'] 7 | 8 | -- ## Text 9 | do 10 | -- Tooltip - Normal - Extended 11 | local text = '' 12 | .. '-' 13 | .. ' %% to do x damage.|n' 14 | .. '-' 15 | .. ' 24%% chance to cast a damage Ancient Blood' 16 | .. ' Lightning spell, costing mana.|n' 17 | .. '-' 18 | .. ' +12%% chance to cast Ancient Blood Lightning for each' 19 | .. ' additional Blood Stone or Ancient Blood Stone.|n' 20 | 21 | for level = 1, 11 do 22 | ability.aub1.values[level] = 23 | string.format(text, level, level, level, level) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /share/objects/specials/malachite/01-malachite.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Malachite 8 | do 9 | local unit = objects[id(globals.Gem_Special__MALACHITE_1)] 10 | 11 | -- ## Combat 12 | do 13 | -- Acquisition Range 14 | unit.uacq.value = 800 15 | end 16 | 17 | -- ## Combat - Attack 1 18 | do 19 | -- Cooldown 20 | unit.ua1c.value = 0.45 21 | 22 | -- Range 23 | unit.ua1r.value = 800 24 | end 25 | end 26 | 27 | -- # Malachite Information 28 | do 29 | local ability = objects.A03D 30 | 31 | -- ## Data 32 | do 33 | -- Maximum Number of Targets 34 | ability.Efk3.values = { 0 } 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /share/objects/specials/malachite/02-vivid-malachite.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Vivid Malachite 8 | do 9 | local unit = objects[id(globals.Gem_Special__MALACHITE_2)] 10 | 11 | -- ## Combat 12 | do 13 | -- Acquisition Range 14 | unit.uacq.value = 800 15 | end 16 | 17 | -- ## Combat - Attack 1 18 | do 19 | -- Cooldown 20 | unit.ua1c.value = 0.45 21 | 22 | -- Range 23 | unit.ua1r.value = 800 24 | end 25 | end 26 | 27 | -- # Malachite Information 28 | do 29 | local ability = objects.A03E 30 | 31 | -- ## Data 32 | do 33 | -- Maximum Number of Targets 34 | ability.Efk3.values = { 0 } 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /share/objects/specials/malachite/03-mighty-malachite.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Mighty Malachite 8 | do 9 | local unit = objects[id(globals.Gem_Special__MALACHITE_3)] 10 | 11 | -- ## Combat - Attack 1 12 | do 13 | -- Cooldown 14 | unit.ua1c.value = 0.45 15 | end 16 | 17 | -- ## Stats 18 | do 19 | -- Gold Cost 20 | unit.ugol.value = 180 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /share/objects/specials/red-crystal/03-rose-quartz-crystal.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ids = { 5 | immolation = 'A01H', 6 | } 7 | 8 | -- # Red Quartz Crystal Immolation 9 | do 10 | local ability = { 11 | type = 'ability', 12 | base = 'ACev', 13 | } 14 | objects[ids.immolation] = ability 15 | 16 | -- ## Art 17 | do 18 | -- Button Position - Normal (X) 19 | ability.abpx = { 20 | type = 'integer', 21 | value = 3, 22 | } 23 | 24 | -- Button Position - Normal (Y) 25 | ability.abpy = { 26 | type = 'integer', 27 | value = 1, 28 | } 29 | 30 | -- Icon - Normal 31 | ability.aart = { 32 | type = 'string', 33 | value = 'ReplaceableTextures\\PassiveButtons\\PASBTNStatUp.blp', 34 | } 35 | end 36 | 37 | -- ## Data 38 | do 39 | -- Chance to Evade 40 | ability.Eev1 = { 41 | data = 1, 42 | type = 'unreal', 43 | values = { 44 | [1] = 0, 45 | }, 46 | } 47 | end 48 | 49 | -- ## Stats 50 | do 51 | -- Area of Effect 52 | ability.aare = { 53 | type = 'unreal', 54 | values = { 55 | [1] = 1500, 56 | }, 57 | } 58 | 59 | -- Cooldown 60 | ability.acdn = { 61 | type = 'unreal', 62 | values = {}, 63 | } 64 | 65 | for level = 1, 11 do 66 | ability.acdn.values[level] = 50 * (1 + 0.1 * (level - 1)) 67 | end 68 | 69 | -- Levels 70 | ability.alev = { 71 | type = 'integer', 72 | value = 11, 73 | } 74 | 75 | -- Race 76 | ability.arac = { 77 | type = 'string', 78 | value = 'human', 79 | } 80 | end 81 | 82 | -- ## Text 83 | do 84 | -- Editor Suffix 85 | ability.ansf = { 86 | type = 'string', 87 | value = '(Rose Quartz Crystal)', 88 | } 89 | 90 | -- Name 91 | ability.anam = { 92 | type = 'string', 93 | value = 'Abilities II', 94 | } 95 | 96 | -- Tooltip - Normal 97 | ability.atp1 = { 98 | type = 'string', 99 | values = { 100 | [1] = '|cff33ff33Rose Quartz Crystal Abilities|r', 101 | }, 102 | } 103 | 104 | -- Tooltip - Normal - Extended 105 | ability.aub1 = { 106 | type = 'string', 107 | values = {}, 108 | } 109 | 110 | local text = 'Enemies within <%s,Area1> range will receive' 111 | .. ' <%s,Cool%d> spell damage per second.' 112 | 113 | for level = 1, 11 do 114 | ability.aub1.values[level] = 115 | string.format(text, ids.immolation, ids.immolation, level) 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /share/objects/specials/silver/01-silver.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Silver 8 | local unit = objects[id(globals.Gem_Special__SILVER_1)] 9 | 10 | -- ## Combat - Attack 1 11 | do 12 | -- Area of Effect (Full Damage) 13 | unit.ua1f.value = 350 14 | 15 | -- Area of Effect (Medium Damage) 16 | unit.ua1h.value = 0 17 | 18 | -- Area of Effect (Small Damage) 19 | unit.ua1q.value = 0 20 | 21 | -- Damage Base 22 | unit.ua1b.value = 25 23 | end 24 | -------------------------------------------------------------------------------- /share/objects/specials/silver/02-sterling-silver.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local deep_copy = require('lib.gem.deep_copy') 6 | local id = require('lib.gem.id') 7 | 8 | -- # Silver 9 | local unit = objects[id(globals.Gem_Special__SILVER_2)] 10 | 11 | -- ## Abilities 12 | do 13 | unit.uabi.value = 'A050' 14 | end 15 | 16 | -- ## Combat - Attack 1 17 | do 18 | -- Area of Effect (Full Damage) 19 | unit.ua1f.value = 350 20 | 21 | -- Area of Effect (Medium Damage) 22 | unit.ua1h.value = 0 23 | 24 | -- Area of Effect (Small Damage) 25 | unit.ua1q.value = 0 26 | 27 | -- Damage Base 28 | unit.ua1b.value = 50 29 | end 30 | 31 | -- # Silver 2 Information 32 | objects.A050 = deep_copy(objects.A00L) 33 | -------------------------------------------------------------------------------- /share/objects/specials/silver/03-silver-knight.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local deep_copy = require('lib.gem.deep_copy') 6 | local id = require('lib.gem.id') 7 | 8 | -- # Silver 9 | local unit = objects[id(globals.Gem_Special__SILVER_3)] 10 | 11 | -- ## Abilities 12 | do 13 | unit.uabi.value = 'A051' 14 | end 15 | 16 | -- ## Combat - Attack 1 17 | do 18 | -- Area of Effect (Full Damage) 19 | unit.ua1f.value = 350 20 | 21 | -- Area of Effect (Medium Damage) 22 | unit.ua1h.value = 0 23 | 24 | -- Area of Effect (Small Damage) 25 | unit.ua1q.value = 0 26 | 27 | -- Damage Base 28 | unit.ua1b.value = 187 29 | end 30 | 31 | -- ## Stats 32 | do 33 | -- Gold Cost 34 | unit.ugol.value = 190 35 | end 36 | 37 | -- # Silver 3 Information 38 | objects.A051 = deep_copy(objects.A00L) 39 | -------------------------------------------------------------------------------- /share/objects/specials/star-ruby/01-star-ruby.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ids = { 5 | immolation = 'A00H', 6 | } 7 | 8 | -- # Star Ruby Immolation 9 | do 10 | local ability = { 11 | type = 'ability', 12 | base = 'ACev', 13 | } 14 | objects[ids.immolation] = ability 15 | 16 | -- ## Art 17 | do 18 | -- Button Position - Normal (X) 19 | ability.abpx = { 20 | type = 'integer', 21 | value = 3, 22 | } 23 | 24 | -- Button Position - Normal (Y) 25 | ability.abpy = { 26 | type = 'integer', 27 | value = 1, 28 | } 29 | 30 | -- Icon - Normal 31 | ability.aart = { 32 | type = 'string', 33 | value = 'ReplaceableTextures\\PassiveButtons\\PASBTNStatUp.blp', 34 | } 35 | end 36 | 37 | -- ## Data 38 | do 39 | -- Chance to Evade 40 | ability.Eev1 = { 41 | data = 1, 42 | type = 'unreal', 43 | values = { 44 | [1] = 0, 45 | }, 46 | } 47 | end 48 | 49 | -- ## Stats 50 | do 51 | -- Area of Effect 52 | ability.aare = { 53 | type = 'unreal', 54 | values = { 55 | [1] = 265, 56 | }, 57 | } 58 | 59 | -- Cooldown 60 | ability.acdn = { 61 | type = 'unreal', 62 | values = {}, 63 | } 64 | 65 | for level = 1, 11 do 66 | ability.acdn.values[level] = 30 * (1 + 0.1 * (level - 1)) 67 | end 68 | 69 | -- Levels 70 | ability.alev = { 71 | type = 'integer', 72 | value = 11, 73 | } 74 | 75 | -- Race 76 | ability.arac = { 77 | type = 'string', 78 | value = 'human', 79 | } 80 | end 81 | 82 | -- ## Text 83 | do 84 | -- Editor Suffix 85 | ability.ansf = { 86 | type = 'string', 87 | value = '(Star Ruby)', 88 | } 89 | 90 | -- Name 91 | ability.anam = { 92 | type = 'string', 93 | value = 'Abilities', 94 | } 95 | 96 | -- Tooltip - Normal 97 | ability.atp1 = { 98 | type = 'string', 99 | values = { 100 | [1] = '|cff33ff33Star Ruby Abilities|r', 101 | }, 102 | } 103 | 104 | -- Tooltip - Normal - Extended 105 | ability.aub1 = { 106 | type = 'string', 107 | values = {}, 108 | } 109 | 110 | local text = 'Enemies within <%s,Area1> range will receive' 111 | .. ' <%s,Cool%d> spell damage per second.' 112 | 113 | for level = 1, 11 do 114 | ability.aub1.values[level] = 115 | string.format(text, ids.immolation, ids.immolation, level) 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /share/objects/specials/star-ruby/02-blood-star.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ids = { 5 | immolation = 'A015', 6 | } 7 | 8 | -- # Blood Star Immolation 9 | do 10 | local ability = { 11 | type = 'ability', 12 | base = 'ACev', 13 | } 14 | objects[ids.immolation] = ability 15 | 16 | -- ## Art 17 | do 18 | -- Button Position - Normal (X) 19 | ability.abpx = { 20 | type = 'integer', 21 | value = 3, 22 | } 23 | 24 | -- Button Position - Normal (Y) 25 | ability.abpy = { 26 | type = 'integer', 27 | value = 1, 28 | } 29 | 30 | -- Icon - Normal 31 | ability.aart = { 32 | type = 'string', 33 | value = 'ReplaceableTextures\\PassiveButtons\\PASBTNStatUp.blp', 34 | } 35 | end 36 | 37 | -- ## Data 38 | do 39 | -- Chance to Evade 40 | ability.Eev1 = { 41 | data = 1, 42 | type = 'unreal', 43 | values = { 44 | [1] = 0, 45 | }, 46 | } 47 | end 48 | 49 | -- ## Stats 50 | do 51 | -- Area of Effect 52 | ability.aare = { 53 | type = 'unreal', 54 | values = { 55 | [1] = 500, 56 | }, 57 | } 58 | 59 | -- Cooldown 60 | ability.acdn = { 61 | type = 'unreal', 62 | values = {}, 63 | } 64 | 65 | for level = 1, 11 do 66 | ability.acdn.values[level] = 40 * (1 + 0.1 * (level - 1)) 67 | end 68 | 69 | -- Levels 70 | ability.alev = { 71 | type = 'integer', 72 | value = 11, 73 | } 74 | 75 | -- Race 76 | ability.arac = { 77 | type = 'string', 78 | value = 'human', 79 | } 80 | end 81 | 82 | -- ## Text 83 | do 84 | -- Editor Suffix 85 | ability.ansf = { 86 | type = 'string', 87 | value = '(Blood Star)', 88 | } 89 | 90 | -- Name 91 | ability.anam = { 92 | type = 'string', 93 | value = 'Abilities', 94 | } 95 | 96 | -- Tooltip - Normal 97 | ability.atp1 = { 98 | type = 'string', 99 | values = { 100 | [1] = '|cff33ff33Blood Star Abilities|r', 101 | }, 102 | } 103 | 104 | -- Tooltip - Normal - Extended 105 | ability.aub1 = { 106 | type = 'string', 107 | values = {}, 108 | } 109 | 110 | local text = 'Enemies within <%s,Area1> range will receive' 111 | .. ' <%s,Cool%d> spell damage per second.' 112 | 113 | for level = 1, 11 do 114 | ability.aub1.values[level] = 115 | string.format(text, ids.immolation, ids.immolation, level) 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /share/objects/specials/star-ruby/03-fire-star.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Fire Star 8 | local unit = objects[id(globals.Gem_Special__STAR_RUBY_3)] 9 | 10 | -- ## Stats 11 | do 12 | -- Gold Cost 13 | unit.ugol.value = 190 14 | 15 | -- Attack 1 Cooldown 16 | unit.ua1c.value = 2.0 17 | 18 | -- Attack 1 Damage Base 19 | unit.ua1b.value = 0 20 | end 21 | 22 | -- # Fire Star Description 23 | do 24 | local ability = objects.A02F 25 | 26 | -- ## Stats 27 | do 28 | -- Area of Effect 29 | for level = 1, 11 do 30 | ability.aare.values[level] = 600 31 | end 32 | 33 | -- Cooldown 34 | for level = 1, 11 do 35 | ability.acdn.values[level] = 0.5 36 | end 37 | 38 | -- Level 39 | ability.alev = { 40 | type = 'integer', 41 | value = 11, 42 | } 43 | 44 | -- Targets Allowed 45 | for level = 1, 11 do 46 | ability.atar.values[level] = 'enemies' 47 | end 48 | end 49 | 50 | -- ## Data 51 | do 52 | -- The default values for these are acceptable. The damage event 53 | -- effectively nullifies all damage anyway. 54 | ability.Efk1 = nil 55 | ability.Efk2 = nil 56 | end 57 | 58 | -- ## Text 59 | do 60 | -- Tooltip - Normal - Extended 61 | local radius = 192 62 | local damage = 60 63 | local per = damage * 0.1 64 | local text = 'Covers enemies in fire, causing targets ' 65 | .. 'to burn like a Star Ruby. The marked target, and enemies ' 66 | .. 'within %d range of it, will take %d spell damage per ' 67 | .. 'second for the next 6.0 seconds. Additional attacks only ' 68 | .. 'refreshes this duration.' 69 | 70 | for level = 1, 11 do 71 | ability.aub1.values[level] = 72 | string.format(text, radius, damage + per * (level - 1)) 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /share/objects/specials/stone-of-bryvx.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | local stone_of_bryvx = id(globals.Gem_Special__STONE_OF_BRYVX) 7 | 8 | -- # Stone of Bryvx 9 | do 10 | local unit = objects[stone_of_bryvx] 11 | 12 | -- ## Abilities 13 | 14 | -- Normal 15 | unit.uabi.value = unit.uabi.value .. ',A03B' 16 | 17 | -- ## Stats 18 | 19 | -- Point Value 20 | unit.upoi = { 21 | type = 'integer', 22 | value = 1500, 23 | } 24 | end 25 | -------------------------------------------------------------------------------- /share/objects/specials/uranium.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local deep_copy = require('lib.gem.deep_copy') 4 | 5 | -- # Uranium 235 6 | do 7 | local unit = objects.h02N 8 | 9 | -- ## Ablities 10 | do 11 | unit.uabi.value = 'A03B,A016,A0U0' 12 | end 13 | 14 | -- ## Combat 15 | do 16 | -- Attack 2 - Damage Base 17 | unit.ua2b.value = 19 18 | end 19 | 20 | -- ## Text 21 | do 22 | -- Hotkey 23 | unit.uhot = { 24 | type = 'string', 25 | value = 'R', 26 | } 27 | end 28 | end 29 | 30 | -- # Uranium 235 Ability 31 | do 32 | local ability = objects.A016 33 | 34 | -- ## Data 35 | do 36 | -- Damage Per Target 37 | ability.Efk1.value = 19 38 | end 39 | end 40 | 41 | -- # Uranium 238 42 | do 43 | local unit = objects.h019 44 | unit.uabi.value = 'A03B,A00W' 45 | end 46 | 47 | -- # Uranium Slow 48 | do 49 | local ability = objects.A00W 50 | ability.Uau1.values[1] = -0.50 51 | 52 | for level = 1, 11 do 53 | ability.Uau1.values[level] = ability.Uau1.values[1] 54 | ability.Uau2.values[level] = ability.Uau2.values[1] 55 | ability.aare.values[level] = ability.aare.values[1] 56 | ability.atar.values[level] = ability.atar.values[1] 57 | ability.abuf.values[level] = ability.abuf.values[1] 58 | end 59 | 60 | ability.alev = { 61 | type = 'integer', 62 | value = 11, 63 | } 64 | end 65 | 66 | -- # Uranium 235 Slow 67 | objects.A0U0 = deep_copy(objects.A00W) 68 | -------------------------------------------------------------------------------- /share/objects/specials/uranium/immolation.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | local ids = { 5 | immolation = 'A00K', 6 | } 7 | 8 | -- # Uranium Immolation 9 | do 10 | local ability = { 11 | type = 'ability', 12 | base = 'ACev', 13 | } 14 | objects[ids.immolation] = ability 15 | 16 | -- ## Art 17 | do 18 | -- Button Position - Normal (X) 19 | ability.abpx = { 20 | type = 'integer', 21 | value = 3, 22 | } 23 | 24 | -- Button Position - Normal (Y) 25 | ability.abpy = { 26 | type = 'integer', 27 | value = 1, 28 | } 29 | 30 | -- Icon - Normal 31 | ability.aart = { 32 | type = 'string', 33 | value = 'ReplaceableTextures\\PassiveButtons\\PASBTNStatUp.blp', 34 | } 35 | end 36 | 37 | -- ## Data 38 | do 39 | -- Chance to Evade 40 | ability.Eev1 = { 41 | data = 1, 42 | type = 'unreal', 43 | values = { 44 | [1] = 0, 45 | }, 46 | } 47 | end 48 | 49 | -- ## Stats 50 | do 51 | -- Area of Effect 52 | ability.aare = { 53 | type = 'unreal', 54 | values = { 55 | [1] = 500, 56 | }, 57 | } 58 | 59 | -- Cooldown 60 | ability.acdn = { 61 | type = 'unreal', 62 | values = {}, 63 | } 64 | 65 | for level = 1, 11 do 66 | ability.acdn.values[level] = 200 * (1 + 0.1 * (level - 1)) 67 | end 68 | 69 | -- Levels 70 | ability.alev = { 71 | type = 'integer', 72 | value = 11, 73 | } 74 | 75 | -- Race 76 | ability.arac = { 77 | type = 'string', 78 | value = 'human', 79 | } 80 | end 81 | 82 | -- ## Text 83 | do 84 | -- Editor Suffix 85 | ability.ansf = { 86 | type = 'string', 87 | value = '(Uranium)', 88 | } 89 | 90 | -- Name 91 | ability.anam = { 92 | type = 'string', 93 | value = 'Abilities II', 94 | } 95 | 96 | -- Tooltip - Normal 97 | ability.atp1 = { 98 | type = 'string', 99 | values = { 100 | [1] = '|cff33ff33Uranium Abilities 2|r', 101 | }, 102 | } 103 | 104 | -- Tooltip - Normal - Extended 105 | ability.aub1 = { 106 | type = 'string', 107 | values = {}, 108 | } 109 | 110 | local text = 'Enemies within <%s,Area1> range will receive' 111 | .. ' <%s,Cool%d> spell damage per second.' 112 | 113 | for level = 1, 11 do 114 | ability.aub1.values[level] = 115 | string.format(text, ids.immolation, ids.immolation, level) 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /share/objects/specials/yellow-sapphire/01-yellow-sapphire.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Yellow Sapphire 8 | local unit = objects[id(globals.Gem_Special__YELLOW_SAPPHIRE_1)] 9 | 10 | -- ## Combat - Attack 1 11 | do 12 | -- Area of Effect (Full Damage) 13 | unit.ua1f.value = 500 14 | 15 | -- Area of Effect (Medium Damage) 16 | unit.ua1h.value = 0 17 | 18 | -- Area of Effect (Small Damage) 19 | unit.ua1q.value = 0 20 | 21 | -- Cooldown Time 22 | unit.ua1c.value = 0.8 23 | end 24 | -------------------------------------------------------------------------------- /share/objects/specials/yellow-sapphire/02-star-yellow-sapphire.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | local globals = map.globals 4 | 5 | local id = require('lib.gem.id') 6 | 7 | -- # Star Yellow Sapphire 8 | local unit = objects[id(globals.Gem_Special__YELLOW_SAPPHIRE_2)] 9 | 10 | -- ## Abilities 11 | do 12 | -- Normal 13 | unit.uabi.value = unit.uabi.value:gsub('A06T,', '') 14 | end 15 | 16 | -- ## Combat - Attack 1 17 | do 18 | -- Area of Effect (Full Damage) 19 | unit.ua1f.value = 500 20 | 21 | -- Area of Effect (Medium Damage) 22 | unit.ua1h.value = 0 23 | 24 | -- Area of Effect (Small Damage) 25 | unit.ua1q.value = 0 26 | 27 | -- Damage Base 28 | unit.ua1b.value = 219 29 | end 30 | -------------------------------------------------------------------------------- /share/objects/standardize-slate-range.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Slate Attack Range (Melee) 5 | -- 6 | -- Make all slates have the same attack range for the 'melee' style attack. 7 | -- For slates with a 'melee' attack, it is always the first attack type. 8 | 9 | local slates = { 10 | 'n000', -- Air 11 | 'n002', -- Hold 12 | 'n003', -- Ancient 13 | 14 | 'n001', -- Slow 15 | 'n004', -- Opal Vein 16 | 'n005', -- Wraith 17 | 18 | 'n008', -- Poison 19 | 'n009', -- Spell 20 | 'n00A', -- Elder 21 | 22 | 'n00C', -- Damage 23 | } 24 | 25 | for _, id in ipairs(slates) do 26 | local slate = objects[id] 27 | 28 | if slate then 29 | -- Combat: Attack 1 - Range 30 | slate.ua1r = { 31 | type = 'integer', 32 | value = 128, 33 | } 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /share/objects/stone-of-bryvx.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Stone of Bryvx Aura 5 | do 6 | local ability = objects.A068 7 | 8 | -- ## Data 9 | do 10 | -- Attack Damage Increase 11 | ability.Cac1.values = { 0.30 } 12 | end 13 | 14 | -- ## Text 15 | do 16 | -- Tooltip - Normal - Extended 17 | ability.aub1.values = { 18 | 'Grants % increased damage to friendly ' 19 | .. 'structures within range.', 20 | } 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /share/objects/type-projectiles.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local globals = map.globals 3 | local objects = map.objects 4 | 5 | do 6 | local chipped = string.pack('>I4', globals.Gem_Gems__EMERALD_CHIPPED) 7 | local flawed = string.pack('>I4', globals.Gem_Gems__EMERALD_FLAWED) 8 | 9 | objects[chipped].ua1m = objects[flawed].ua1m 10 | end 11 | 12 | do 13 | local chipped = string.pack('>I4', globals.Gem_Gems__RUBY_CHIPPED) 14 | local great = string.pack('>I4', globals.Gem_Gems__RUBY_GREAT) 15 | 16 | objects[great].ua1m = objects[chipped].ua1m 17 | 18 | local id = 'A06Y' 19 | objects[id].amat = objects[chipped].ua1m 20 | end 21 | -------------------------------------------------------------------------------- /share/objects/unit-disarm.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Unit Disarm 5 | -- 6 | -- This system makes use of Cargo Hold (`'Abun'`) to disable a unit's attack. 7 | 8 | -- ## Disarm Buff 9 | objects['UDDB'] = { 10 | type = 'buff', 11 | base = 'Basl', 12 | 13 | -- ### Art 14 | 15 | -- Icon 16 | fart = { 17 | type = 'string', 18 | value = 'ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp', 19 | }, 20 | 21 | -- Target 22 | ftat = { 23 | type = 'string', 24 | value = '', 25 | }, 26 | 27 | -- Target Attachment Point 1 28 | fta0 = { 29 | type = 'string', 30 | value = '', 31 | }, 32 | 33 | -- ### Text 34 | 35 | -- Editor Suffix 36 | fnsf = { 37 | type = 'string', 38 | value = '(Unit Disarm)', 39 | }, 40 | 41 | -- Name (Editor Only) 42 | fnam = { 43 | type = 'string', 44 | value = 'Disarm Buff', 45 | }, 46 | 47 | -- Tooltip 48 | ftip = { 49 | type = 'string', 50 | value = 'Disarmed', 51 | }, 52 | 53 | -- Tooltip - Extended 54 | fube = { 55 | type = 'string', 56 | value = 'This unit is disarmed: it cannot attack.', 57 | }, 58 | } 59 | 60 | -- ## Disarm Temporary 61 | objects['UDDT'] = { 62 | type = 'ability', 63 | base = 'Aasl', 64 | 65 | -- ### Data/Stats 66 | 67 | -- Area of Effect 68 | aare = { 69 | type = 'unreal', 70 | values = { 71 | [1] = 0, 72 | }, 73 | }, 74 | 75 | -- Buffs 76 | abuf = { 77 | type = 'string', 78 | values = { 79 | [1] = 'UDDB', 80 | }, 81 | }, 82 | 83 | -- Movement Speed Factor 84 | Slo1 = { 85 | data = 1, 86 | type = 'unreal', 87 | values = { 88 | [1] = 0, 89 | }, 90 | }, 91 | 92 | -- Targets Allowed 93 | atar = { 94 | type = 'string', 95 | values = { 96 | [1] = 'self', 97 | }, 98 | }, 99 | 100 | -- ### Text 101 | 102 | -- Editor Suffix 103 | ansf = { 104 | type = 'string', 105 | value = '(Unit Disarm)', 106 | }, 107 | 108 | -- Name 109 | anam = { 110 | type = 'string', 111 | value = 'Disarm Temporary', 112 | }, 113 | } 114 | 115 | -- ## Disarm Ability 116 | objects['UDDA'] = { 117 | type = 'ability', 118 | base = 'Abun', 119 | 120 | -- ### Data/Stats 121 | 122 | -- Cargo Capacity 123 | Car1 = { 124 | data = 1, 125 | type = 'integer', 126 | values = { 127 | [1] = 0, 128 | }, 129 | }, 130 | 131 | -- ### Text 132 | 133 | -- Editor Suffix 134 | ansf = { 135 | type = 'string', 136 | value = '(Unit Disarm)', 137 | }, 138 | 139 | -- Name 140 | anam = { 141 | type = 'string', 142 | value = 'Disarm Ability', 143 | }, 144 | } 145 | -------------------------------------------------------------------------------- /share/objects/unit-event.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Unit Event: Detect Leave. 5 | objects['UEDL'] = { 6 | type = 'ability', 7 | base = 'Adef', 8 | 9 | anam = { 10 | type = 'string', 11 | value = 'Detect Leave', 12 | }, 13 | 14 | ansf = { 15 | type = 'string', 16 | value = '(Unit Event)', 17 | }, 18 | 19 | aart = { 20 | type = 'string', 21 | value = '', 22 | }, 23 | 24 | auar = { 25 | type = 'string', 26 | value = '', 27 | }, 28 | 29 | arac = { 30 | type = 'string', 31 | value = 'other', 32 | }, 33 | } 34 | 35 | -- Unit Event: Detect Damage 36 | objects['UEDD'] = { 37 | type = 'ability', 38 | base = 'AIsr', 39 | 40 | anam = { 41 | type = 'string', 42 | value = 'Detect Damage', 43 | }, 44 | 45 | ansf = { 46 | type = 'string', 47 | value = '(Unit Event)', 48 | }, 49 | 50 | aite = { 51 | type = 'integer', 52 | value = 0, 53 | }, 54 | 55 | isr2 = { 56 | data = 2, 57 | type = 'unreal', 58 | values = { 59 | [1] = 2.0, 60 | }, 61 | }, 62 | } 63 | -------------------------------------------------------------------------------- /share/objects/unit-state.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local globals = map.globals 3 | local objects = map.objects 4 | 5 | -- # Unit State 6 | -- 7 | -- Provides abilities to assist in setting `UNIT_STATE_MAX_LIFE` and 8 | -- `UNIT_STATE_MAX_MANA`. For more details, see the Unit State source file. 9 | 10 | local function to_code (value) 11 | return string.pack('>I4', value) 12 | end 13 | 14 | local life = to_code(globals.Unit_State___MAXIMUM_LIFE) 15 | local mana = to_code(globals.Unit_State___MAXIMUM_MANA) 16 | 17 | local powers = globals.Unit_State___MAXIMUM_POWER 18 | local levels = 2 * powers + 3 19 | 20 | local abilities = { 21 | [life] = { 22 | name = 'Unit State Maximum Life', 23 | base = 'AIlf', 24 | field = 'Ilif', -- Data - Max Life Gained 25 | }, 26 | 27 | [mana] = { 28 | name = 'Unit State Maximum Mana', 29 | base = 'AImz', 30 | field = 'Iman', -- Data - Max Mana Gained 31 | }, 32 | } 33 | 34 | for id, info in pairs(abilities) do 35 | local ability = { 36 | type = 'ability', 37 | base = info.base, 38 | } 39 | 40 | objects[id] = ability 41 | 42 | -- ## Stats 43 | 44 | -- Item Ability 45 | ability.aite = { 46 | type = 'integer', 47 | value = 0, 48 | } 49 | 50 | -- Levels 51 | ability.alev = { 52 | type = 'integer', 53 | value = levels, 54 | } 55 | 56 | -- ## Data 57 | ability[info.field] = { 58 | data = 1, 59 | type = 'integer', 60 | values = { 61 | [1] = 0, 62 | }, 63 | } 64 | 65 | for power = 0, powers do 66 | local value = math.pow(2, power) 67 | local level = power + 2 68 | 69 | ability[info.field].values[level] = value 70 | ability[info.field].values[powers + level + 1] = -value 71 | end 72 | 73 | -- ## Text 74 | 75 | -- Editor Suffix 76 | ability.ansf = { 77 | type = 'string', 78 | value = '', 79 | } 80 | 81 | -- Name 82 | ability.anam = { 83 | type = 'string', 84 | value = info.name, 85 | } 86 | end 87 | -------------------------------------------------------------------------------- /share/objects/unit-stun.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- # Unit Stun 5 | 6 | -- ## Stun Buff 7 | objects['USSB'] = { 8 | type = 'buff', 9 | base = 'BSTN', 10 | 11 | -- ### ART 12 | 13 | -- Target 14 | ftat = { 15 | type = 'string', 16 | value = '', 17 | }, 18 | 19 | -- Target Attachment Point 1 20 | fta0 = { 21 | type = 'string', 22 | value = '', 23 | }, 24 | 25 | -- ### Text 26 | 27 | -- Editor Suffix 28 | fnsf = { 29 | type = 'string', 30 | value = '(Unit Stun)', 31 | }, 32 | 33 | -- Name (Editor Only) 34 | fnam = { 35 | type = 'string', 36 | value = 'Stun Buff', 37 | }, 38 | 39 | -- Tooltip 40 | ftip = { 41 | type = 'string', 42 | value = 'Stunned', 43 | }, 44 | 45 | -- Tooltip - Extended 46 | fube = { 47 | type = 'string', 48 | value = 'This unit is stunned: it cannot move or perform actions.', 49 | }, 50 | } 51 | 52 | -- ## Stun Ability 53 | -- 54 | -- Seems like a good choice. Alternatives include Storm Bolt or Bash, but 55 | -- Firebolt seems to be more common. 56 | objects['USSA'] = { 57 | type = 'ability', 58 | base = 'ACfb', 59 | 60 | -- ## Art 61 | 62 | -- Missile Art 63 | amat = { 64 | type = 'string', 65 | value = '', 66 | }, 67 | 68 | -- Missile Speed 69 | amsp = { 70 | type = 'integer', 71 | value = 0, 72 | }, 73 | 74 | -- ### Data/Stats 75 | 76 | -- Buffs 77 | abuf = { 78 | type = 'string', 79 | values = { 80 | [1] = 'USSB', 81 | }, 82 | }, 83 | 84 | -- Cast Range 85 | -- 86 | -- So Nestharus claims this is the maximum range. No clue if this is true, 87 | -- but let's go with it. The alternative being the diagnol of the maximum 88 | -- map size (480 x 480). 89 | aran = { 90 | type = 'unreal', 91 | values = { 92 | [1] = 92083, 93 | }, 94 | }, 95 | 96 | -- Cooldown 97 | acdn = { 98 | type = 'unreal', 99 | values = { 100 | [1] = 0, 101 | }, 102 | }, 103 | 104 | -- Damage 105 | Htb1 = { 106 | data = 1, 107 | type = 'unreal', 108 | values = { 109 | 0.0, 110 | }, 111 | }, 112 | 113 | -- Duration (Normal) 114 | adur = { 115 | type = 'unreal', 116 | values = { 117 | [1] = 0, 118 | }, 119 | }, 120 | 121 | -- Duration (Hero) 122 | ahdu = { 123 | type = 'unreal', 124 | values = { 125 | [1] = 0, 126 | }, 127 | }, 128 | 129 | -- Levels 130 | alev = { 131 | type = 'integer', 132 | value = 1, 133 | }, 134 | 135 | -- Mana Cost 136 | amcs = { 137 | type = 'integer', 138 | values = { 139 | [1] = 0, 140 | }, 141 | }, 142 | 143 | -- Race 144 | arac = { 145 | type = 'string', 146 | value = 'commoner', 147 | }, 148 | 149 | -- Required Level 150 | -- 151 | -- This is needed to be able to stun units with spell immunity. 152 | arlv = { 153 | type = 'integer', 154 | value = 6, 155 | }, 156 | 157 | -- Targets Allowed 158 | -- 159 | -- This is needed to stun all types of units. 160 | atar = { 161 | type = 'string', 162 | values = { 163 | [1] = 'invulnerable,vulnerable', 164 | }, 165 | }, 166 | 167 | -- ### Text 168 | 169 | -- Editor Suffix 170 | ansf = { 171 | type = 'string', 172 | value = '(Unit Stun)', 173 | }, 174 | 175 | -- Name 176 | anam = { 177 | type = 'string', 178 | value = 'Stun Ability', 179 | }, 180 | 181 | -- Order String - Use/Turn On 182 | aord = { 183 | type = 'string', 184 | value = 'firebolt', 185 | }, 186 | } 187 | -------------------------------------------------------------------------------- /share/objects/unlock-barrage-cap.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Towers that can attack all nearby enemies have, up to now, been set 5 | -- individually. This can be changed in the future to utilize a single 6 | -- ability for all. Until then, make changes here. 7 | 8 | -- Other towers are already handled elsewhere. 9 | local abilities = { 10 | 'A073', -- Range Slate 11 | 'A074', -- Viper Slate 12 | 'A016', -- Uranium 235 13 | 'A03F', -- Mighty Malachite 14 | 'A02F', -- Fire Star 15 | } 16 | 17 | local targets = { 18 | data = 3, 19 | type = 'integer', 20 | values = { 0 }, 21 | } 22 | 23 | for _, ability in ipairs(abilities) do 24 | objects[ability].Efk3 = targets 25 | end 26 | -------------------------------------------------------------------------------- /share/objects/unused-objects.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Used in old range check. 5 | objects['n00D'] = nil 6 | objects['n006'] = nil 7 | 8 | -- Old difficulty aura buffs. 9 | objects['B003'] = nil 10 | objects['B009'] = nil 11 | 12 | -- Buffs from old Immolation. 13 | objects['B00E'] = nil 14 | objects['B00C'] = nil 15 | objects['B00S'] = nil 16 | objects['B00D'] = nil 17 | objects['B00U'] = nil 18 | 19 | -- Anti-Stick 20 | objects['A02Y'] = nil 21 | 22 | -- Star Yellow Sapphire aura. 23 | objects['A06T'] = nil 24 | 25 | -- Great Amethyst ability. 26 | objects['A01I'] = nil 27 | 28 | -- Spell Slate. 29 | objects.A05Q = nil 30 | objects.A05T = nil 31 | 32 | -- Elder Slate. 33 | objects.A05Y = nil 34 | objects.A060 = nil 35 | objects.A062 = nil 36 | 37 | local ids = { 38 | -- Bonus armor aura buffs. 39 | 'B00O', 40 | 'B00P', 41 | 'B00Q', 42 | 43 | -- Star Yellow Sapphire aura buff. 44 | 'B00N', 45 | 46 | -- Spell armor reduction buff. 47 | 'B00K', 48 | } 49 | 50 | for _, id in ipairs(ids) do 51 | objects[id] = nil 52 | end 53 | -------------------------------------------------------------------------------- /share/objects/update-map-information.lua: -------------------------------------------------------------------------------- 1 | local map = ... 2 | local objects = map.objects 3 | 4 | -- Middle fountain. 5 | if objects['h027'] then 6 | local unit = objects['h027'] 7 | 8 | unit.unam = { 9 | type = 'string', 10 | value = string.format( 11 | '|cfffed312%s by %s|r', 12 | map.header.name, 13 | map.globals.Gem__MAINTAINER 14 | ), 15 | } 16 | end 17 | -------------------------------------------------------------------------------- /src/array.j: -------------------------------------------------------------------------------- 1 | // # Array 2 | // 3 | // Trying to set an index outside the range `[0, 8191]` will silently fail and 4 | // break save/load functionality. Attempting to retrieve a value outside of 5 | // these bounds will return an arbitrary value dependent on the type. 6 | // 7 | // In addition, the index `8191`, while perfectly fine in most cases, cannot be 8 | // used or save/load functionality with also break. All of this causes us to 9 | // constrain ourselves to indices within the range `[0, 8190]`. 10 | 11 | globals 12 | constant integer Array__MINIMUM_INDEX = 0 13 | constant integer Array__MAXIMUM_INDEX = 8190 14 | 15 | constant integer Array__MAXIMUM_SIZE = 8191 16 | endglobals 17 | -------------------------------------------------------------------------------- /src/clock.j: -------------------------------------------------------------------------------- 1 | globals 2 | integer Clock___Start = -1 3 | timerdialog Clock___Dialog = null 4 | framehandle Clock___Frame = null 5 | endglobals 6 | 7 | function Clock___Update takes nothing returns boolean 8 | local string time = Board___Time (Time__Now () - Clock___Start) 9 | call BlzFrameSetText (Clock___Frame, time) 10 | 11 | return true 12 | endfunction 13 | 14 | function Clock__Started takes nothing returns integer 15 | return Clock___Start 16 | endfunction 17 | 18 | function Clock__Start takes nothing returns nothing 19 | local integer context 20 | 21 | set Clock___Start = Time__Now () 22 | set Clock___Dialog = CreateTimerDialog (null) 23 | 24 | call TimerDialogSetTitle (Clock___Dialog, "Game Time:") 25 | call TimerDialogSetTimeColor (Clock___Dialog, 255, 255, 255, 0) 26 | call TimerDialogDisplay (Clock___Dialog, true) 27 | 28 | set context = -1 29 | loop 30 | set context = context + 1 31 | set Clock___Frame = BlzGetFrameByName ("TimerDialogValue", context) 32 | exitwhen BlzFrameIsVisible (Clock___Frame) 33 | endloop 34 | 35 | call BlzFrameSetText (Clock___Frame, "00:00:00") 36 | 37 | call Run__Every (0.10, function Clock___Update) 38 | endfunction 39 | -------------------------------------------------------------------------------- /src/color.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant string Color__WHITE = "ffffff" 3 | constant string Color__RED = "ff0000" 4 | constant string Color__GOLD = "fed312" 5 | constant string Color__LINK = "00ff00" 6 | endglobals 7 | 8 | function Color takes string color, string text returns string 9 | return "|cff" + color + text + "|r" 10 | endfunction 11 | 12 | function Color__White takes string text returns string 13 | return Color (Color__WHITE, text) 14 | endfunction 15 | 16 | function Color__Red takes string text returns string 17 | return Color (Color__RED, text) 18 | endfunction 19 | 20 | function Color__Gold takes string text returns string 21 | return Color (Color__GOLD, text) 22 | endfunction 23 | 24 | function Color__Link takes string text returns string 25 | return Color (Color__LINK, text) 26 | endfunction 27 | 28 | function Color__Reset takes nothing returns string 29 | return "|r" 30 | endfunction 31 | -------------------------------------------------------------------------------- /src/commands.j: -------------------------------------------------------------------------------- 1 | function Commands__Initialize takes nothing returns boolean 2 | call Commands___Initialize_Debug () 3 | call Commands___Initialize_Zoom () 4 | call Commands___Initialize_Maze () 5 | call Commands___Initialize_Bars () 6 | call Commands___Initialize_Extra () 7 | 8 | return false 9 | endfunction 10 | -------------------------------------------------------------------------------- /src/commands/debug.j: -------------------------------------------------------------------------------- 1 | // # Commands: Debug 2 | // 3 | // The purpose of this command is to deal with issues where no solution has 4 | // been found, and to provide blanket coverage for issues that may or may not 5 | // be encountered by the user. 6 | // 7 | // The hope is that if this command is used and actually addresses an issue, 8 | // then the user will report the behavior and the bug involved. 9 | // 10 | // ## Depends 11 | // 12 | // - `Gem` 13 | // - `Gem 3.1` 14 | 15 | // ## Globals 16 | 17 | globals 18 | group Commands___Debug_Group = CreateGroup () 19 | endglobals 20 | 21 | // ## Functions 22 | 23 | // Ensure that units stuck at the player's spawn point receive the 'move' 24 | // order. This will only work for creep units. 25 | function Commands___Debug_Move takes nothing returns boolean 26 | local unit the_unit = GetFilterUnit () 27 | local rect the_rect 28 | local player computer = GetOwningPlayer (the_unit) 29 | local integer owner_id 30 | 31 | if Gem_Player__Is_Monster (computer) then 32 | set owner_id = GetPlayerId (computer) - 11 33 | set the_rect = udg_Move1st [owner_id + 1] 34 | 35 | call IssuePointOrder (the_unit, "move", GetRectCenterX (the_rect), GetRectCenterY (the_rect)) 36 | endif 37 | 38 | return false 39 | endfunction 40 | 41 | // The primary function for the debug command. 42 | function Commands___Debug takes nothing returns boolean 43 | local player the_player 44 | local integer player_index 45 | 46 | set the_player = GetTriggerPlayer () 47 | set player_index = GetPlayerId (the_player) 48 | 49 | call DisplayTextToPlayer (the_player, 0.00, 0.00, "Debugging...") 50 | call DisplayTextToPlayer (the_player, 0.00, 0.00, "If this command fixes your issue, please file a bug report.") 51 | 52 | call GroupEnumUnitsInRect (Commands___Debug_Group, udg_Spawn [player_index + 1], Filter (function Commands___Debug_Move)) 53 | 54 | if GetLocalPlayer () == the_player then 55 | call EnableUserControl (true) 56 | call EnableUserUI (true) 57 | call EnableSelect (true, true) 58 | call EnablePreSelect (true, true) 59 | call EnableDragSelect (true, true) 60 | endif 61 | 62 | return false 63 | endfunction 64 | 65 | // Initializes the debug command. 66 | function Commands___Initialize_Debug takes nothing returns nothing 67 | local trigger the_trigger 68 | local player the_player 69 | local integer player_index 70 | 71 | set the_trigger = CreateTrigger () 72 | 73 | set player_index = 0 74 | loop 75 | set the_player = Player (player_index) 76 | 77 | call TriggerRegisterPlayerChatEvent (the_trigger, the_player, "-debug", true) 78 | 79 | set player_index = player_index + 1 80 | exitwhen player_index >= bj_MAX_PLAYERS 81 | endloop 82 | 83 | call TriggerAddCondition (the_trigger, Condition (function Commands___Debug)) 84 | 85 | endfunction 86 | -------------------------------------------------------------------------------- /src/commands/extra.j: -------------------------------------------------------------------------------- 1 | globals 2 | boolean array Commands___No_Extra_Chance 3 | endglobals 4 | 5 | function Commands__Is_No_Extra_Chance takes player whom returns boolean 6 | return Commands___No_Extra_Chance [GetPlayerId (whom)] 7 | endfunction 8 | 9 | function Commands___Extra takes nothing returns boolean 10 | local player whom = GetTriggerPlayer () 11 | local integer whom_id = GetPlayerId (whom) 12 | local boolean no_extra 13 | local boolean started 14 | local string status 15 | 16 | set started = Gem_Rank__Get_Level (whom_id) > 1 17 | set started = started or Gem_Placement__Placed (whom) > 0 18 | set started = started or Gem_Rank__Get_Start (whom_id, 1) > 0 19 | 20 | if started then 21 | call DisplayTextToPlayer (whom, 0.0, 0.0, "The `-extra` command can only be used before placing a gem at game start") 22 | return true 23 | endif 24 | 25 | set no_extra = not Commands___No_Extra_Chance [whom_id] 26 | set Commands___No_Extra_Chance [whom_id] = no_extra 27 | call Gem_Mine__Swap_Placeholders (whom) 28 | 29 | if no_extra then 30 | set status = "disabled" 31 | else 32 | set status = "enabled" 33 | endif 34 | 35 | set status = "Extra Chance has been " + status 36 | 37 | if Clock__Started () < 0 then 38 | call Settings__Display_Welcome (status) 39 | else 40 | call DisplayTextToPlayer (whom, 0.0, 0.0, status) 41 | endif 42 | 43 | return true 44 | endfunction 45 | 46 | function Commands___Initialize_Extra takes nothing returns nothing 47 | local trigger extra 48 | local integer index 49 | local player whom 50 | 51 | set extra = CreateTrigger () 52 | call Trigger__Try (extra, function Commands___Extra) 53 | 54 | set index = 0 55 | loop 56 | set whom = Player (index) 57 | call TriggerRegisterPlayerChatEvent (extra, whom, "-extra", true) 58 | 59 | set index = index + 1 60 | exitwhen index >= bj_MAX_PLAYERS 61 | endloop 62 | endfunction 63 | -------------------------------------------------------------------------------- /src/commands/zoom.j: -------------------------------------------------------------------------------- 1 | globals 2 | // The changes to zoom are applied instantly. 3 | constant real Commands___ZOOM_DURATION = 0.0 4 | endglobals 5 | 6 | function Commands___Zoom takes nothing returns boolean 7 | local string the_string 8 | local integer value 9 | 10 | set the_string = GetEventPlayerChatString () 11 | set value = S2I (SubString (the_string, 6, StringLength (the_string))) 12 | 13 | // Do not further process the 'zoom' command in replays. This ensures 14 | // that watchers maintain a consistent viewing experience. 15 | if Game_Status () == Game_Status__REPLAY then 16 | return false 17 | endif 18 | 19 | if GetLocalPlayer () == GetTriggerPlayer () then 20 | call SetCameraField (CAMERA_FIELD_TARGET_DISTANCE, value, Commands___ZOOM_DURATION) 21 | endif 22 | 23 | return false 24 | endfunction 25 | 26 | function Commands___Initialize_Zoom takes nothing returns nothing 27 | local integer player_index 28 | local player the_player 29 | local trigger the_trigger 30 | 31 | // Set a 'sane' default zoom for replays. 32 | if Game_Status () == Game_Status__REPLAY then 33 | call SetCameraField (CAMERA_FIELD_TARGET_DISTANCE, 2500, Commands___ZOOM_DURATION) 34 | endif 35 | 36 | set the_trigger = CreateTrigger () 37 | 38 | set player_index = 0 39 | loop 40 | set the_player = Player (player_index) 41 | 42 | call TriggerRegisterPlayerChatEvent (the_trigger, the_player, "-zoom ", false) 43 | 44 | set player_index = player_index + 1 45 | exitwhen player_index >= bj_MAX_PLAYERS 46 | endloop 47 | 48 | call TriggerAddCondition (the_trigger, Condition (function Commands___Zoom)) 49 | 50 | endfunction 51 | -------------------------------------------------------------------------------- /src/config.j: -------------------------------------------------------------------------------- 1 | function config takes nothing returns nothing 2 | local integer i 3 | local integer j 4 | 5 | local player o 6 | local player p 7 | 8 | call SetMapName ("TRIGSTR_001") 9 | call SetTeams (1) 10 | call SetPlayers (8) 11 | 12 | call SetGamePlacement(MAP_PLACEMENT_FIXED) 13 | call DefineStartLocation(0,-2304.0,7424.0) 14 | call DefineStartLocation(1,2304.0,7424.0) 15 | call DefineStartLocation(2,7680.0,2048.0) 16 | call DefineStartLocation(3,7680.0,-2560.0) 17 | call DefineStartLocation(4,2304.0,-8000.0) 18 | call DefineStartLocation(5,-2304.0,-8000.0) 19 | call DefineStartLocation(6,-7488.0,-2560.0) 20 | call DefineStartLocation(7,-7680.0,2048.0) 21 | 22 | set i = 0 23 | loop 24 | set p = Player (i) 25 | 26 | call ForcePlayerStartLocation (p, i) 27 | call SetPlayerColor (p, ConvertPlayerColor (i)) 28 | call SetPlayerRacePreference (p, RACE_PREF_RANDOM) 29 | call SetPlayerRaceSelectable (p, true) 30 | call SetPlayerState(p, PLAYER_STATE_ALLIED_VICTORY, 1) 31 | call SetPlayerTeam (p, 0) 32 | 33 | // Neutrals, specifically the gamblers in the middle. 34 | if i == 8 then 35 | // Used to temporary hold the player's units while placing gems. 36 | elseif i == 9 then 37 | call SetPlayerController(p, MAP_CONTROL_RESCUABLE) 38 | else 39 | call SetPlayerController (p, MAP_CONTROL_USER) 40 | endif 41 | 42 | set j = i + 1 43 | loop 44 | set o = Player (j) 45 | 46 | if p != o then 47 | call SetPlayerAlliance (p, o, ALLIANCE_PASSIVE, true) 48 | call SetPlayerAlliance (p, o, ALLIANCE_SHARED_VISION, true) 49 | 50 | call SetPlayerAlliance (o, p, ALLIANCE_PASSIVE, true) 51 | call SetPlayerAlliance (o, p, ALLIANCE_SHARED_VISION, true) 52 | 53 | if j == 9 then 54 | call SetPlayerAlliance (o, p, ALLIANCE_RESCUABLE, true) 55 | endif 56 | endif 57 | 58 | set j = j + 1 59 | exitwhen j > 9 60 | endloop 61 | 62 | set i = i + 1 63 | exitwhen i > 8 64 | endloop 65 | 66 | set i = 11 67 | loop 68 | set p = Player (i) 69 | call SetPlayerColor (p, PLAYER_COLOR_BROWN) 70 | call SetPlayerRacePreference (p, RACE_PREF_UNDEAD) 71 | call SetPlayerRaceSelectable (p, false) 72 | call SetPlayerController (p, MAP_CONTROL_COMPUTER) 73 | call SetPlayerTeam (p, 1) 74 | 75 | set i = i + 1 76 | exitwhen i > 18 77 | endloop 78 | endfunction 79 | -------------------------------------------------------------------------------- /src/detect-placed-gem-death.j: -------------------------------------------------------------------------------- 1 | // Detect Placed Gem Death 2 | // ======================= 3 | // 4 | // The point of this system is simple: detect when a player opts to kill all 5 | // five of their placed gems. Without this system that player's game would end 6 | // when they opt for total gem annihilation. When the event is detected, we 7 | // finish the building period and begin the level. 8 | // 9 | // Depends 10 | // ------- 11 | // 12 | // - Gem 3.1 13 | // - Gem Gems 14 | // - Gem Placement 15 | // - Unit Event 16 | // 17 | // Notes 18 | // ----- 19 | // 20 | // - This module can be removed after disabling the ability to attack friendly 21 | // structures. 22 | 23 | globals 24 | integer array Detect_Placed_Gem_Death___Count 25 | endglobals 26 | 27 | function Detect_Placed_Gem_Death___On_Placement takes nothing returns boolean 28 | local player placement__player 29 | local integer placement__player_index 30 | 31 | set placement__player = Gem_Placement__The_Player () 32 | set placement__player_index = GetPlayerId (placement__player) 33 | 34 | if Gem_Placement__Placed (placement__player) == 1 then 35 | set Detect_Placed_Gem_Death___Count [placement__player_index] = 0 36 | endif 37 | 38 | return false 39 | endfunction 40 | 41 | function Detect_Placed_Gem_Death___On_Death takes nothing returns boolean 42 | local unit dead 43 | local player owner 44 | local integer owner_index 45 | local integer count 46 | 47 | set dead = Unit_Event__The_Unit () 48 | set owner = GetOwningPlayer (dead) 49 | set owner_index = GetPlayerId (owner) 50 | 51 | if not Gem_Player__Is_Player (owner) then 52 | return false 53 | endif 54 | 55 | // Only consider units belonging to this player that die during their 56 | // building period. 57 | if not udg_RaceBuildingPeriod [owner_index + 1] then 58 | return false 59 | endif 60 | 61 | if not Gem_Gems__Is_Gem (GetUnitTypeId (dead)) then 62 | return false 63 | endif 64 | 65 | set count = Detect_Placed_Gem_Death___Count [owner_index] + 1 66 | set Detect_Placed_Gem_Death___Count [owner_index] = count 67 | 68 | if count >= 5 then 69 | call DisplayTextToPlayer (owner, 0.0, 0.0, Color ("66ffff", "You have destroyed all your gems this round!")) 70 | 71 | if owner_index == 0 then 72 | call Trig_Finish_Build_Race_P1_Actions () 73 | elseif owner_index == 1 then 74 | call Trig_Finish_Build_Race_P2_Actions () 75 | elseif owner_index == 2 then 76 | call Trig_Finish_Build_Race_P3_Actions () 77 | elseif owner_index == 3 then 78 | call Trig_Finish_Build_Race_P4_Actions () 79 | elseif owner_index == 4 then 80 | call Trig_Finish_Build_Race_P5_Actions () 81 | elseif owner_index == 5 then 82 | call Trig_Finish_Build_Race_P6_Actions () 83 | elseif owner_index == 6 then 84 | call Trig_Finish_Build_Race_P7_Actions () 85 | elseif owner_index == 7 then 86 | call Trig_Finish_Build_Race_P8_Actions () 87 | endif 88 | endif 89 | 90 | return false 91 | endfunction 92 | 93 | function Detect_Placed_Gem_Death__Initialize takes nothing returns boolean 94 | call Unit_Event__On_Death (Condition (function Detect_Placed_Gem_Death___On_Death)) 95 | call Gem_Placement__On_Placement (Condition (function Detect_Placed_Gem_Death___On_Placement)) 96 | 97 | return false 98 | endfunction 99 | -------------------------------------------------------------------------------- /src/effect.j: -------------------------------------------------------------------------------- 1 | globals 2 | effect array Effect___SFX 3 | endglobals 4 | 5 | function Effect___Expires takes nothing returns boolean 6 | local integer runner = Run__Scheduled () 7 | 8 | call DestroyEffect (Effect___SFX [runner]) 9 | set Effect___SFX [runner] = null 10 | 11 | return true 12 | endfunction 13 | 14 | function Effect__Set_Lifespan takes effect sfx, real duration returns nothing 15 | local integer runner 16 | 17 | if sfx == null then 18 | return 19 | endif 20 | 21 | if duration < 0.0 then 22 | set duration = 0.0 23 | endif 24 | 25 | set runner = Run__After (duration, function Effect___Expires) 26 | 27 | if runner != Run__NULL then 28 | set Effect___SFX [runner] = sfx 29 | endif 30 | endfunction 31 | -------------------------------------------------------------------------------- /src/error.j: -------------------------------------------------------------------------------- 1 | globals 2 | // These two values can be set to indicate the presence of an error, as 3 | // well as helping to indicate the location where it occurred. The 4 | // values are intended to be significant only when the return value of 5 | // a call indicates an error (e.g. returning `false`). 6 | string Error = null 7 | string Label = null 8 | 9 | integer Error__Code = 0 10 | string Error__Message = null 11 | endglobals 12 | 13 | function Error takes integer error, string message returns nothing 14 | set Error__Code = error 15 | set Error__Message = message 16 | endfunction 17 | 18 | function Error__Clear takes nothing returns nothing 19 | call Error (0, null) 20 | endfunction 21 | -------------------------------------------------------------------------------- /src/fix/dialog-user-control.j: -------------------------------------------------------------------------------- 1 | // A user's control can be disabled if they pass multiple dialog button 2 | // events in quick succession. The solution is fairly simple: just use 3 | // `EnableUserControl ()` for the affected user. 4 | // 5 | // This behavior was exhibited pre-1.28.0, and it has not been verified whether 6 | // it occurs in later versions. 7 | function Fix__Dialog_User_Control takes player whom returns boolean 8 | if GetLocalPlayer () == whom then 9 | call EnableUserControl (true) 10 | endif 11 | 12 | return false 13 | endfunction 14 | -------------------------------------------------------------------------------- /src/fix/stuck-tooltip.j: -------------------------------------------------------------------------------- 1 | // # Fix Stuck Tooltip 2 | // 3 | // If a player's mouse is positioned just right (e.g. over a minimap button) 4 | // during initialization, the resulting tooltip can become permanently stuck. 5 | // It will not disappear, despite other tooltips displaying properly 6 | // underneath. 7 | // 8 | // A solution to remove the tooltip after is has begun to misbehave has not 9 | // been found. However, this fix prevents the tooltip from misbehaving in the 10 | // first place. 11 | // 12 | // This fix does present a few negative side effects: 13 | // 14 | // - The function `ShowInterface ()` is utilized to hide the UI during map 15 | // loaing and show it again on map start. This presents a possible conflict 16 | // should an existing system have certain expectations regarding such 17 | // behavior. 18 | // - On Ghost++ bots that make use of the `map_loadingame` setting, players 19 | // will have their UI disabled until all other players have loaded. The 20 | // primary negative here is the inability to use chat messages (e.g. 21 | // Battle.net commands and map specific commands). 22 | // 23 | // ## Depends 24 | // 25 | // - Game 26 | 27 | function Fix_Stuck_Tooltip___On_Start takes nothing returns boolean 28 | call ShowInterface (true, 0.00) 29 | 30 | return false 31 | endfunction 32 | 33 | function Fix_Stuck_Tooltip__Initialize takes nothing returns boolean 34 | call ShowInterface (false, 0.00) 35 | call Game__On_Start (Condition (function Fix_Stuck_Tooltip___On_Start)) 36 | 37 | return false 38 | endfunction 39 | -------------------------------------------------------------------------------- /src/fix/upgrade-scale.j: -------------------------------------------------------------------------------- 1 | // # Upgrade Scale 2 | // 3 | // When a unit upgrade is finished or cancelled the scale of the unit can be 4 | // wrong. This keeps that behavior from presenting. 5 | 6 | function Fix_Upgrade_Scale___Event takes nothing returns boolean 7 | local unit which = GetTriggerUnit () 8 | local real scale = BlzGetUnitRealField (which, UNIT_RF_SCALING_VALUE) 9 | 10 | call SetUnitScale (which, scale, scale, scale) 11 | 12 | return true 13 | endfunction 14 | 15 | function Fix_Upgrade_Scale__Initialize takes nothing returns boolean 16 | local trigger upgrade 17 | 18 | set upgrade = Trigger__New () 19 | call Trigger__Try (upgrade, function Fix_Upgrade_Scale___Event) 20 | call TriggerRegisterAnyUnitEventBJ (upgrade, EVENT_PLAYER_UNIT_UPGRADE_CANCEL) 21 | call TriggerRegisterAnyUnitEventBJ (upgrade, EVENT_PLAYER_UNIT_UPGRADE_FINISH) 22 | 23 | return false 24 | endfunction 25 | -------------------------------------------------------------------------------- /src/game-status.j: -------------------------------------------------------------------------------- 1 | // # Game Status 2 | // 3 | // Detect if a game is offline, online, or a replay. 4 | // 5 | // ## Credits 6 | // 7 | // A facsimile of [GameStatus][1] by TriggerHappy. 8 | // 9 | // [1]: https://www.hiveworkshop.com/threads/gamestatus-replay-detection.293176 10 | 11 | globals 12 | constant integer Game_Status___UNIT_ID = 'hfoo' 13 | 14 | constant integer Game_Status__OFFLINE = 0 15 | constant integer Game_Status__ONLINE = 1 16 | constant integer Game_Status__REPLAY = 2 17 | 18 | integer Game_Status___Status 19 | endglobals 20 | 21 | function Game_Status takes nothing returns integer 22 | return Game_Status___Status 23 | endfunction 24 | 25 | function Game_Status__Initialize takes nothing returns boolean 26 | local player whom 27 | local integer whom_id = 0 28 | local boolean is_user 29 | local boolean is_playing 30 | 31 | local unit which 32 | local boolean is_selected 33 | 34 | // Get the first human player. 35 | loop 36 | set whom = Player (whom_id) 37 | set is_user = GetPlayerController (whom) == MAP_CONTROL_USER 38 | set is_playing = GetPlayerSlotState (whom) == PLAYER_SLOT_STATE_PLAYING 39 | exitwhen is_user and is_playing 40 | set whom_id = whom_id + 1 41 | endloop 42 | 43 | // Force that player to select a unit. 44 | set which = CreateUnit (whom, Game_Status___UNIT_ID, 0., 0., 0.) 45 | call SelectUnit (which, true) 46 | set is_selected = IsUnitSelected (which, whom) 47 | call RemoveUnit (which) 48 | 49 | if is_selected then 50 | if ReloadGameCachesFromDisk () then 51 | set Game_Status___Status = Game_Status__OFFLINE 52 | else 53 | set Game_Status___Status = Game_Status__REPLAY 54 | endif 55 | else 56 | set Game_Status___Status = Game_Status__ONLINE 57 | endif 58 | 59 | return false 60 | endfunction 61 | -------------------------------------------------------------------------------- /src/game.j: -------------------------------------------------------------------------------- 1 | // # Game 2 | 3 | globals 4 | constant trigger Game___IS_SAVED = CreateTrigger () 5 | constant trigger Game___IS_LOADED = CreateTrigger () 6 | endglobals 7 | 8 | function Game___Destroy_Trigger takes nothing returns boolean 9 | call DestroyTrigger (GetTriggeringTrigger ()) 10 | 11 | return false 12 | endfunction 13 | 14 | // Registers the provided `callback` to fire once the game starts (that is, 15 | // immediately upon entering the map after loading). This is known as the 16 | // 'On_Start' event. 17 | function Game__On_Start takes boolexpr callback returns nothing 18 | local trigger on_start 19 | 20 | set on_start = CreateTrigger () 21 | 22 | call TriggerRegisterTimerEvent (on_start, 0.00, false) 23 | call TriggerAddCondition (on_start, callback) 24 | call TriggerAddCondition (on_start, Condition (function Game___Destroy_Trigger)) 25 | endfunction 26 | 27 | function Game__Is_Loaded takes nothing returns boolean 28 | return GetTriggerEvalCount (Game___IS_LOADED) > 0 29 | endfunction 30 | 31 | function Game__Is_Saved takes nothing returns boolean 32 | return GetTriggerEvalCount (Game___IS_SAVED) > 0 33 | endfunction 34 | 35 | function Game__Initialize takes nothing returns boolean 36 | call TriggerRegisterGameEvent (Game___IS_SAVED, EVENT_GAME_SAVE) 37 | call TriggerRegisterGameEvent (Game___IS_LOADED, EVENT_GAME_LOADED) 38 | 39 | return false 40 | endfunction 41 | -------------------------------------------------------------------------------- /src/gem-3.1/miner-flashing.j: -------------------------------------------------------------------------------- 1 | globals 2 | trigger array udg_Miner_Flashing 3 | integer Miner_Flashing___ID_MINER = ID__NULL 4 | endglobals 5 | 6 | function Miner_Flashing___Core takes nothing returns nothing 7 | local unit miner 8 | 9 | set miner = LoadUnitHandle (Table, Miner_Flashing___ID_MINER, GetHandleId (GetTriggeringTrigger ())) 10 | 11 | call TriggerSleepAction (1.00) 12 | call SetUnitVertexColor (miner, 255, 0, 0, 255) 13 | 14 | call TriggerSleepAction (1.00) 15 | call SetUnitVertexColor (miner, 255, 0, 255, 255) 16 | 17 | call TriggerSleepAction (1.00) 18 | call SetUnitVertexColor (miner, 0, 0, 255, 255) 19 | 20 | call TriggerSleepAction (1.00) 21 | call SetUnitVertexColor (miner, 0, 255, 255, 255) 22 | 23 | call TriggerSleepAction (1.00) 24 | call SetUnitVertexColor (miner, 255, 255, 255, 255) 25 | endfunction 26 | 27 | function Miner_Flashing takes player the_player returns nothing 28 | local trigger flash 29 | 30 | if not Gem_Player__Is_Player (the_player) then 31 | return 32 | endif 33 | 34 | set flash = udg_Miner_Flashing [GetPlayerId (the_player)] 35 | 36 | if flash == null then 37 | set flash = CreateTrigger () 38 | call TriggerAddAction (flash, function Miner_Flashing___Core) 39 | 40 | if Miner_Flashing___ID_MINER == ID__NULL then 41 | set Miner_Flashing___ID_MINER = ID () 42 | endif 43 | 44 | call SaveUnitHandle (Table, Miner_Flashing___ID_MINER, GetHandleId (flash), Gem_Player__Get_Miner (the_player)) 45 | endif 46 | 47 | call TriggerExecute (flash) 48 | endfunction 49 | -------------------------------------------------------------------------------- /src/gem.j: -------------------------------------------------------------------------------- 1 | // # Gem 2 | // 3 | // This system contains map specific information that is expected 4 | // to be referenced elsewhere. 5 | globals 6 | constant string Gem__NAME = "Gem TD+" 7 | constant string Gem__NAME_PATH = "Gem TD Plus" 8 | constant string Gem__NAME_FULL = "Gem Tower Defense Plus" 9 | 10 | constant string Gem__MAINTAINER = "NVS#12194" 11 | 12 | constant string Gem__WEBSITE_DISCORD = "https://discord.gg/PxNNp77" 13 | constant string Gem__WEBSITE_REPOSITORY = "https://github.com/nvs/gem" 14 | 15 | constant integer Gem__MAXIMUM_PLAYERS = 8 16 | 17 | constant integer Gem__PLAYER_CREEPS_INDEX = 11 18 | constant player Gem__PLAYER_CREEPS = Player (Gem__PLAYER_CREEPS_INDEX) 19 | 20 | // This is not a unique game identifier. That is not its purpose. The 21 | // point is to allow verification that a screenshot pairs to a replay in 22 | // an easy, albeit not foolproof, way. 23 | constant integer Gem__GAME_ID = GetRandomInt (0, 2147483647) 24 | endglobals 25 | -------------------------------------------------------------------------------- /src/gem/critters.j: -------------------------------------------------------------------------------- 1 | function Gem_Critters__Initialize takes nothing returns nothing 2 | local integer id = 'Ng00' 3 | local integer last = 'Ng0e' 4 | 5 | local real x 6 | local real y 7 | local player passive = Player (PLAYER_NEUTRAL_PASSIVE) 8 | local unit which 9 | 10 | loop 11 | set x = GetRandomReal (-512.0, 512.0) 12 | set y = GetRandomReal (-768.0, 256.0) 13 | set which = CreateUnit (passive, id, x, y, bj_UNIT_FACING) 14 | 15 | if id == 'Ng00' or id == 'Ng03' then 16 | call AddSpecialEffectTarget ("Abilities\\Spells\\Human\\InnerFire\\InnerFireTarget.mdl", which, "overhead") 17 | endif 18 | 19 | set id = id + 1 20 | exitwhen id > 'Ng0e' 21 | endloop 22 | endfunction 23 | -------------------------------------------------------------------------------- /src/gem/extra-chance/menu.j: -------------------------------------------------------------------------------- 1 | globals 2 | boolean array Gem_Extra_Chance_Menu___IS_DISPLAYED 3 | 4 | constant integer Gem_Extra_Chance_Menu___TARGET = ID () 5 | constant integer Gem_Extra_Chance_Menu___NAME = ID () 6 | endglobals 7 | 8 | function Gem_Extra_Chance_Menu__Display takes player whom, dialog window, string title returns nothing 9 | local integer whom_id = GetPlayerId (whom) 10 | 11 | if Gem_Extra_Chance_Menu___IS_DISPLAYED [whom_id] then 12 | call DisplayTextToPlayer (whom, 0, 0, "Extra Chance menu is already open") 13 | return 14 | endif 15 | 16 | set Gem_Extra_Chance_Menu___IS_DISPLAYED [whom_id] = true 17 | call DialogSetMessage (window, title) 18 | call DialogDisplay (whom, window, true) 19 | endfunction 20 | 21 | function Gem_Extra_Chance_Menu___Button takes nothing returns boolean 22 | local player whom = GetTriggerPlayer () 23 | local integer whom_id = GetPlayerId (whom) 24 | local dialog window = GetClickedDialog () 25 | local button pane = GetClickedButton () 26 | local integer pane_id = GetHandleId (pane) 27 | local integer target = LoadInteger (Table, pane_id, Gem_Extra_Chance_Menu___TARGET) 28 | local string name = LoadStr (Table, pane_id, Gem_Extra_Chance_Menu___NAME) 29 | local boolean is_active = Gem_Extra_Chance__Is_Active (whom) 30 | local string message 31 | local integer previous 32 | local integer current 33 | local integer bonus 34 | 35 | set Label = "Gem_Extra_Chance_Menu___Button" 36 | 37 | call Fix__Dialog_User_Control (whom) 38 | set Gem_Extra_Chance_Menu___IS_DISPLAYED [whom_id] = false 39 | call DialogDisplay (whom, window, false) 40 | 41 | if target <= 0 then 42 | // Do nothing. 43 | elseif not Gem_Extra_Chance__Set (whom, target) then 44 | if Error__Code == ERROR__PLACEMENT_HAS_STARTED then 45 | call DisplayTextToPlayer (whom, 0, 0, "Extra Chance cannot be changed during placement") 46 | endif 47 | else 48 | set previous = Gem_Extra_Chance__Previous_Target (whom) 49 | set current = Gem_Extra_Chance__Current_Target (whom) 50 | 51 | if is_active and previous != current then 52 | set message = "Switching" 53 | else 54 | set message = "Setting" 55 | endif 56 | 57 | set bonus = Gem_Extra_Chance__Current_Bonus (whom) 58 | call DisplayTextToPlayer (whom, 0, 0, message + " Extra Chance to " + name + " (" + I2S (bonus) + "x)") 59 | endif 60 | 61 | return true 62 | endfunction 63 | 64 | function Gem_Extra_Chance_Menu__Initialize takes nothing returns nothing 65 | local trigger rule = CreateTrigger () 66 | 67 | call Trigger__Try (rule, function Gem_Extra_Chance_Menu___Button) 68 | call Gem_Extra_Chance_Menu_Type__Initialize (rule) 69 | call Gem_Extra_Chance_Menu_Slate__Initialize (rule) 70 | endfunction 71 | -------------------------------------------------------------------------------- /src/gem/extra-chance/menu/slate.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant dialog Gem_Extra_Chance_Menu_Slate___DIALOG = DialogCreate () 3 | constant string Gem_Extra_Chance_Menu_Slate___TITLE = "Extra Chance Slate" 4 | endglobals 5 | 6 | function Gem_Extra_Chance_Menu_Slate__Display takes player whom returns nothing 7 | local dialog window = Gem_Extra_Chance_Menu_Slate___DIALOG 8 | local string title = Gem_Extra_Chance_Menu_Slate___TITLE 9 | 10 | call Gem_Extra_Chance_Menu__Display (whom, window, title) 11 | endfunction 12 | 13 | function Gem_Extra_Chance_Menu_Slate__Initialize takes trigger rule returns nothing 14 | local dialog window = Gem_Extra_Chance_Menu_Slate___DIALOG 15 | local button pane 16 | local integer pane_id 17 | 18 | local string array names 19 | local integer array targets 20 | local integer array hotkeys 21 | local string array labels 22 | local integer index = -1 23 | 24 | call TriggerRegisterDialogEvent (rule, window) 25 | 26 | set names [0] = "Hold Slate" 27 | set targets [0] = Gem_Slate__HOLD 28 | set hotkeys [0] = 'H' 29 | set labels [0] = Color__White ("H") + Color__Gold ("old") 30 | 31 | set names [1] = "Air Slate" 32 | set targets [1] = Gem_Slate__AIR 33 | set hotkeys [1] = 'A' 34 | set labels [1] = Color__White ("A") + Color__Gold ("ir") 35 | 36 | set names [2] = "Opal Vein Slate" 37 | set targets [2] = Gem_Slate__OPAL_VEIN 38 | set hotkeys [2] = 'O' 39 | set labels [2] = Color__White ("O") + Color__Gold ("pal Vein") 40 | 41 | set names [3] = "Slow Slate" 42 | set targets [3] = Gem_Slate__SLOW 43 | set hotkeys [3] = 'S' 44 | set labels [3] = Color__White ("S") + Color__Gold ("low") 45 | 46 | set names [4] = "Spell Slate" 47 | set targets [4] = Gem_Slate__SPELL 48 | set hotkeys [4] = 'E' 49 | set labels [4] = Color__Gold ("Sp") + Color__White ("e") + Color__Gold ("ll") 50 | 51 | set names [5] = "Poison Slate" 52 | set targets [5] = Gem_Slate__POISON 53 | set hotkeys [5] = 'P' 54 | set labels [5] = Color__White ("P") + Color__Gold ("oison") 55 | 56 | set names [6] = "Damage Slate" 57 | set targets [6] = Gem_Slate__DAMAGE 58 | set hotkeys [6] = 'D' 59 | set labels [6] = Color__White ("D") + Color__Gold ("amage") 60 | 61 | set names [7] = "Range Slate" 62 | set targets [7] = Gem_Slate__RANGE 63 | set hotkeys [7] = 'R' 64 | set labels [7] = Color__White ("R") + Color__Gold ("ange") 65 | 66 | set targets [8] = 0 67 | set hotkeys [8] = 'X' 68 | set labels [8] = Color__Gold ("E") + Color__White ("x") + Color__Gold ("it") 69 | 70 | loop 71 | set index = index + 1 72 | exitwhen labels [index] == null 73 | 74 | set pane = DialogAddButton (window, labels [index], hotkeys [index]) 75 | set pane_id = GetHandleId (pane) 76 | 77 | call SaveInteger (Table, pane_id, Gem_Extra_Chance_Menu___TARGET, targets [index]) 78 | call SaveStr (Table, pane_id, Gem_Extra_Chance_Menu___NAME, names [index]) 79 | endloop 80 | endfunction 81 | -------------------------------------------------------------------------------- /src/gem/extra-chance/menu/type.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant dialog Gem_Extra_Chance_Menu_Type___DIALOG = DialogCreate () 3 | constant string Gem_Extra_Chance_Menu_Type___TITLE = "Extra Chance Perfect" 4 | endglobals 5 | 6 | function Gem_Extra_Chance_Menu_Type__Display takes player whom returns nothing 7 | local dialog window = Gem_Extra_Chance_Menu_Type___DIALOG 8 | local string title = Gem_Extra_Chance_Menu_Type___TITLE 9 | 10 | call Gem_Extra_Chance_Menu__Display (whom, window, title) 11 | endfunction 12 | 13 | function Gem_Extra_Chance_Menu_Type__Initialize takes trigger rule returns nothing 14 | local dialog window = Gem_Extra_Chance_Menu_Type___DIALOG 15 | local button pane 16 | local integer pane_id 17 | 18 | local string array names 19 | local integer array targets 20 | local integer array hotkeys 21 | local string array labels 22 | local integer index = -1 23 | 24 | call TriggerRegisterDialogEvent (rule, window) 25 | 26 | set names [0] = "Perfect Amethyst" 27 | set targets [0] = Gem_Gems__AMETHYST_PERFECT 28 | set hotkeys [0] = 'A' 29 | set labels [0] = Color__White ("A") + Color__Gold ("methyst") 30 | 31 | set names [1] = "Perfect Diamond" 32 | set targets [1] = Gem_Gems__DIAMOND_PERFECT 33 | set hotkeys [1] = 'D' 34 | set labels [1] = Color__White ("D") + Color__Gold ("iamond") 35 | 36 | set names [2] = "Perfect Opal" 37 | set targets [2] = Gem_Gems__OPAL_PERFECT 38 | set hotkeys [2] = 'O' 39 | set labels [2] = Color__White ("O") + Color__Gold ("pal") 40 | 41 | set names [3] = "Perfect Sapphire" 42 | set targets [3] = Gem_Gems__SAPPHIRE_PERFECT 43 | set hotkeys [3] = 'S' 44 | set labels [3] = Color__White ("S") + Color__Gold ("apphire") 45 | 46 | set names [4] = "Perfect Ruby" 47 | set targets [4] = Gem_Gems__RUBY_PERFECT 48 | set hotkeys [4] = 'R' 49 | set labels [4] = Color__White ("R") + Color__Gold ("uby") 50 | 51 | set names [5] = "Perfect Topaz" 52 | set targets [5] = Gem_Gems__TOPAZ_PERFECT 53 | set hotkeys [5] = 'T' 54 | set labels [5] = Color__White ("T") + Color__Gold ("opaz") 55 | 56 | set names [6] = "Perfect Emerald" 57 | set targets [6] = Gem_Gems__EMERALD_PERFECT 58 | set hotkeys [6] = 'E' 59 | set labels [6] = Color__White ("E") + Color__Gold ("merald") 60 | 61 | set names [7] = "Perfect Aquamarine" 62 | set targets [7] = Gem_Gems__AQUAMARINE_PERFECT 63 | set hotkeys [7] = 'Q' 64 | set labels [7] = Color__Gold ("A") + Color__White ("q") + Color__Gold ("uamarine") 65 | 66 | set targets [8] = 0 67 | set hotkeys [8] = 'X' 68 | set labels [8] = Color__Gold ("E") + Color__White ("x") + Color__Gold ("it") 69 | 70 | loop 71 | set index = index + 1 72 | exitwhen labels [index] == null 73 | 74 | set pane = DialogAddButton (window, labels [index], hotkeys [index]) 75 | set pane_id = GetHandleId (pane) 76 | 77 | call SaveInteger (Table, pane_id, Gem_Extra_Chance_Menu___TARGET, targets [index]) 78 | call SaveStr (Table, pane_id, Gem_Extra_Chance_Menu___NAME, names [index]) 79 | endloop 80 | endfunction 81 | -------------------------------------------------------------------------------- /src/gem/ground-textures.j: -------------------------------------------------------------------------------- 1 | globals 2 | ubersplat array Gem_Ground_Textures___Splats 3 | constant string Gem_Ground_Textures___PATH = "HSMA" 4 | ubersplat Gem_Ground_Textures___Splat = null 5 | endglobals 6 | 7 | function Gem_Ground_Textures__Prepare takes nothing returns nothing 8 | set Gem_Ground_Textures___Splat = CreateUbersplat (0, 0, "HSMA", 255, 255, 255, 255, true, false) 9 | call DestroyUbersplat (Gem_Ground_Textures___Splat) 10 | 11 | if GetHandleId (Gem_Ground_Textures___Splat) == -1 then 12 | set Gem_Ground_Textures___Splat = null 13 | endif 14 | endfunction 15 | 16 | function Gem_Ground_Textures__Hide takes unit which returns nothing 17 | local integer index 18 | 19 | if which == null then 20 | return 21 | endif 22 | 23 | set index = Unit_Indexer__Unit_Index (which) 24 | call ShowUbersplat (Gem_Ground_Textures___Splats [index], false) 25 | endfunction 26 | 27 | function Gem_Ground_Textures___Leave takes nothing returns nothing 28 | local integer index = Unit_Indexer__The_Index () 29 | set Gem_Ground_Textures___Splats [index] = null 30 | endfunction 31 | 32 | function Gem_Ground_Textures__Register takes unit which returns nothing 33 | local integer index 34 | 35 | if which == null or Gem_Ground_Textures___Splat == null then 36 | return 37 | endif 38 | 39 | set index = Unit_Indexer__Unit_Index (which) 40 | set Gem_Ground_Textures___Splats [index] = Gem_Ground_Textures___Splat 41 | set Gem_Ground_Textures___Splat = null 42 | endfunction 43 | 44 | function Gem_Ground_Textures__Initialize takes nothing returns nothing 45 | call Unit_Event__On_Leave (Condition (function Gem_Ground_Textures___Leave)) 46 | endfunction 47 | -------------------------------------------------------------------------------- /src/gem/information.j: -------------------------------------------------------------------------------- 1 | // # Gem Information 2 | // 3 | // Information entries are located on the left panel of the Quests tab. They 4 | // are displayed in the order they are created. 5 | // 6 | // ## Depends 7 | // 8 | // - Quest 9 | 10 | // Sets up `the_quest` as a new information entry, using the provided `title`, 11 | // `icon`, and `text`. 12 | function Gem_Information__Setup takes quest the_quest, string title, string icon, string text returns nothing 13 | call Quest__Setup (the_quest, title, icon, text, true) 14 | endfunction 15 | 16 | // Adds an item to `the_quest`, using the provided `text` as the description. 17 | function Gem_Information__Item takes quest the_quest, string text returns nothing 18 | call Quest__Item (the_quest, text) 19 | endfunction 20 | -------------------------------------------------------------------------------- /src/gem/information/changelogs.j: -------------------------------------------------------------------------------- 1 | function Gem_Information___Changelogs takes nothing returns nothing 2 | local string title = "Changelogs" 3 | local string icon = "ReplaceableTextures\\CommandButtons\\BTNScrollOfTownPortal.blp" 4 | local string text = "" 5 | 6 | set text = text + "There are no changelogs provided with the map. To view them, visit the GitHub repository:|n|n" 7 | 8 | set text = text + "- " + Color__Link (Gem__WEBSITE_REPOSITORY) 9 | 10 | call Gem_Information__Setup (CreateQuest (), title, icon, text) 11 | endfunction 12 | -------------------------------------------------------------------------------- /src/gem/information/initialize.j: -------------------------------------------------------------------------------- 1 | // # Gem Information 2 | // 3 | // ## Depends 4 | // 5 | // - Game 6 | 7 | function Gem_Information___On_Start takes nothing returns boolean 8 | call Gem_Information___What_Is_Gem_TD_Plus () 9 | call Gem_Information___Changelogs () 10 | call Gem_Information___Random_Information () 11 | 12 | return false 13 | endfunction 14 | 15 | function Gem_Information__Initialize takes nothing returns boolean 16 | call Game__On_Start (Condition (function Gem_Information___On_Start)) 17 | 18 | return false 19 | endfunction 20 | -------------------------------------------------------------------------------- /src/gem/information/random-information.j: -------------------------------------------------------------------------------- 1 | // # Gem Information - Random Information 2 | 3 | function Gem_Information___Random_Information takes nothing returns nothing 4 | local string title 5 | local string icon 6 | local string text 7 | 8 | set title = "Random Information" 9 | set icon = "ReplaceableTextures\\CommandButtons\\BTNScrollOfProtection.blp" 10 | 11 | set text = Color__Gold ("Stuns:") + "|n" 12 | set text = text + "- New stuns cannot be applied until the first one has finished.|n" 13 | set text = text + "- Units have 0.1 seconds of stun immunity after a stun has finished.|n|n" 14 | 15 | set text = text + Color__Gold ("Chain:") + "|n" 16 | set text = text + "- For attacks with chain, the projectile will not travel to the same target twice.|n|n" 17 | 18 | set text = text + Color__Gold ("Triggered Attacks:") + "|n" 19 | set text = text + "- Towers with 1 - 1 damage do not deal attack damage. They merely make use of the attack mechanic to trigger other abilities.|n|n" 20 | 21 | set text = text + Color__Gold ("Buffs and Debuffs:") + "|n" 22 | set text = text + "- Buffs and debuffs stack if they have different names. For example, Black Opal's Strength stacks with Mystic Black Opal's Great Strength. However, Opal Vein Slate's Boost does not stack with Wraith Slate's Boost.|n" 23 | set text = text + "- For same named buffs and debuffs, special rules apply. Unless stated otherwise, a buff or debuff can only be applied one time by any source. If the count limit is reached, then new applications simply overwrite the old. And should a buff or debuff have multiple levels, as is the case with Opal's Haste, the highest level will have priority.|n" 24 | 25 | call Gem_Information__Setup (CreateQuest (), title, icon, text) 26 | endfunction 27 | -------------------------------------------------------------------------------- /src/gem/information/what-is-gem-td-plus.j: -------------------------------------------------------------------------------- 1 | // Gem Information - What Is Gem TD+? 2 | 3 | function Gem_Information___What_Is_Gem_TD_Plus takes nothing returns nothing 4 | local string title 5 | local string icon 6 | local string text 7 | local quest which = CreateQuest () 8 | 9 | set title = "What is " + Gem__NAME + "?" 10 | set icon = "ReplaceableTextures\\CommandButtons\\BTNScrollOfHealing.blp" 11 | 12 | set text = Gem__NAME + ", maintained by " + Color__Red (Gem__MAINTAINER) + ", is an updated version of the original Gem Tower Defense created by " + Color__Red ("Bryvx") + ".|n|n" 13 | 14 | set text = text + "- " + Color__Link (Gem__WEBSITE_DISCORD) + "|n" 15 | set text = text + "- " + Color__Link (Gem__WEBSITE_REPOSITORY) + "|n|n" 16 | 17 | set text = text + "For the latest community news, to meet other players, and to view the leaderboards, one should join the Discord. It aims to serve as the focal point for all things " + Gem__NAME + ".|n|n" 18 | 19 | set text = text + "The repository is more oriented towards the development of the map. It does, however, include the changelogs and represents the only official place to get releases." 20 | 21 | call Gem_Information__Setup (which, title, icon, text) 22 | endfunction 23 | -------------------------------------------------------------------------------- /src/gem/mine/cancel.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Gem_Mine_Cancel___BUTTON_ID = 'GMCB' 3 | constant integer Gem_Mine_Cancel___PLACEHOLDER_ID = 'GMCP' 4 | constant integer Gem_Mine_Cancel___NO_EXTRA_ID = 'GMCN' 5 | 6 | constant string Gem_Mine_Cancel___ORDER = "neutralspell" 7 | constant integer Gem_Mine_Cancel___ORDER_ID = OrderId (Gem_Mine_Cancel___ORDER) 8 | endglobals 9 | 10 | function Gem_Mine_Cancel___Button takes nothing returns boolean 11 | local integer order_id = GetIssuedOrderId () 12 | local player whom 13 | local string message 14 | 15 | set Label = "Gem_Mine_Cancel___Button" 16 | 17 | if order_id != Gem_Mine_Cancel___ORDER_ID then 18 | return true 19 | endif 20 | 21 | set whom = GetTriggerPlayer () 22 | 23 | if GetUnitTypeId (GetTriggerUnit ()) != 'h01V' then 24 | return true 25 | endif 26 | 27 | if Gem_Extra_Chance__Clear (whom) then 28 | set message = "Clearing the Extra Chance target" 29 | elseif Error__Code == ERROR__NOT_ACTIVE then 30 | set message = "Extra Chance is not active and cannot be cleared" 31 | elseif Error__Code == ERROR__PLACEMENT_HAS_STARTED then 32 | set message = "Extra Chance cannot be changed during placement" 33 | else 34 | set message = "Unknown error clearing Extra Chance" 35 | endif 36 | 37 | call DisplayTextToPlayer (whom, 0, 0, message) 38 | 39 | return true 40 | endfunction 41 | 42 | function Gem_Mine_Cancel__Initialize takes trigger rule returns nothing 43 | call Trigger__Try (rule, function Gem_Mine_Cancel___Button) 44 | call Gem_Mine__Add_Research (Gem_Mine_Cancel___BUTTON_ID, Gem_Mine_Cancel___PLACEHOLDER_ID, Gem_Mine_Cancel___NO_EXTRA_ID) 45 | endfunction 46 | -------------------------------------------------------------------------------- /src/gem/mine/information.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Gem_Mine_Information___BUTTON_ID = 'GMIB' 3 | endglobals 4 | -------------------------------------------------------------------------------- /src/gem/mine/slate.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Gem_Mine_Slate___BUTTON_ID = 'GMSB' 3 | constant integer Gem_Mine_Slate___PLACEHOLDER_ID = 'GMSP' 4 | constant integer Gem_Mine_Slate___NO_EXTRA_ID = 'GMSN' 5 | 6 | constant string Gem_Mine_Slate___ORDER = "fanofknives" 7 | constant integer Gem_Mine_Slate___ORDER_ID = OrderId (Gem_Mine_Slate___ORDER) 8 | endglobals 9 | 10 | function Gem_Mine_Slate___Button takes nothing returns boolean 11 | local player whom 12 | 13 | set Label = "Gem_Mine_Slate___Button" 14 | 15 | if GetIssuedOrderId () != Gem_Mine_Slate___ORDER_ID then 16 | return true 17 | endif 18 | 19 | set whom = GetTriggerPlayer () 20 | 21 | if GetUnitTypeId (GetTriggerUnit ()) != 'h01V' then 22 | return true 23 | endif 24 | 25 | call AdjustPlayerStateSimpleBJ (whom, PLAYER_STATE_RESOURCE_GOLD, Gem_Extra_Chance__SLATE_COST) 26 | call Gem_Extra_Chance_Menu_Slate__Display (whom) 27 | 28 | return true 29 | endfunction 30 | 31 | function Gem_Mine_Slate__Initialize takes trigger rule returns nothing 32 | call Trigger__Try (rule, function Gem_Mine_Slate___Button) 33 | call Gem_Mine__Add_Research (Gem_Mine_Slate___BUTTON_ID, Gem_Mine_Slate___PLACEHOLDER_ID, Gem_Mine_Slate___NO_EXTRA_ID) 34 | endfunction 35 | -------------------------------------------------------------------------------- /src/gem/mine/type.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Gem_Mine_Type___BUTTON_ID = 'GMTB' 3 | constant integer Gem_Mine_Type___PLACEHOLDER_ID = 'GMTP' 4 | constant integer Gem_Mine_Type___NO_EXTRA_ID = 'GMTN' 5 | 6 | constant string Gem_Mine_Type___ORDER = "thunderclap" 7 | constant integer Gem_Mine_Type___ORDER_ID = OrderId (Gem_Mine_Type___ORDER) 8 | endglobals 9 | 10 | function Gem_Mine_Type___Button takes nothing returns boolean 11 | local player whom 12 | 13 | set Label = "Gem_Mine_Type___Button" 14 | 15 | if GetIssuedOrderId () != Gem_Mine_Type___ORDER_ID then 16 | return true 17 | endif 18 | 19 | set whom = GetTriggerPlayer () 20 | 21 | if GetUnitTypeId (GetTriggerUnit ()) != 'h01V' then 22 | return true 23 | endif 24 | 25 | call AdjustPlayerStateSimpleBJ (whom, PLAYER_STATE_RESOURCE_GOLD, Gem_Extra_Chance__TYPE_COST) 26 | call Gem_Extra_Chance_Menu_Type__Display (whom) 27 | 28 | return true 29 | endfunction 30 | 31 | function Gem_Mine_Type__Initialize takes trigger rule returns nothing 32 | call Trigger__Try (rule, function Gem_Mine_Type___Button) 33 | call Gem_Mine__Add_Research (Gem_Mine_Type___BUTTON_ID, Gem_Mine_Type___PLACEHOLDER_ID, Gem_Mine_Type___NO_EXTRA_ID) 34 | endfunction 35 | -------------------------------------------------------------------------------- /src/gem/player.j: -------------------------------------------------------------------------------- 1 | // # Gem Player 2 | // 3 | // ## Depends 4 | // 5 | // - Gem 6 | // 7 | // ## Notes 8 | // 9 | // - `Player ()` returns `null` when called with an out of bounds player 10 | // integer. That is, outside the range `[0, 15]`. 11 | // - `GetPlayerId ()` returns `0` when called with `null`. 12 | 13 | globals 14 | unit array Gem_Player___MINER 15 | endglobals 16 | 17 | // Returns a `boolean` indicating whether `the_player` is a valid gem player. 18 | // Note that this does not indicate presence in the game. 19 | function Gem_Player__Is_Player takes player the_player returns boolean 20 | if the_player == null then 21 | return false 22 | endif 23 | 24 | if GetPlayerId (the_player) >= Gem__MAXIMUM_PLAYERS then 25 | return false 26 | endif 27 | 28 | return GetPlayerController (the_player) == MAP_CONTROL_USER 29 | endfunction 30 | 31 | function Gem_Player__Is_Monster takes player whom returns boolean 32 | local integer index 33 | 34 | if whom == null then 35 | return false 36 | endif 37 | 38 | set index = GetPlayerId (whom) 39 | 40 | return 11 <= index and index <= 18 41 | endfunction 42 | 43 | function Gem_Player__Remove_Creeps takes player whom returns nothing 44 | local integer whom_id 45 | local group units 46 | local unit which 47 | 48 | if not Gem_Player__Is_Player (whom) then 49 | return 50 | endif 51 | 52 | set whom_id = GetPlayerId (whom) 53 | set units = CreateGroup () 54 | // Shifting ownership of monsters to individual computer players gives 55 | // the guarantee that all units owned by one is associated with a single 56 | // human player. 57 | call GroupEnumUnitsOfPlayer (units, Player (whom_id + 11), null) 58 | 59 | loop 60 | set which = FirstOfGroup (units) 61 | exitwhen which == null 62 | call GroupRemoveUnit (units, which) 63 | call RemoveUnit (which) 64 | endloop 65 | 66 | call DestroyGroup (units) 67 | endfunction 68 | 69 | // Returns the miner `unit` for `the_player`. Returns `null` for an invalid 70 | // player. 71 | function Gem_Player__Get_Miner takes player the_player returns unit 72 | if not Gem_Player__Is_Player (the_player) then 73 | return null 74 | endif 75 | 76 | return Gem_Player___MINER [GetPlayerId (the_player)] 77 | endfunction 78 | 79 | function Gem_Player__Initialize takes nothing returns boolean 80 | local player the_player 81 | local integer index__player 82 | local real x 83 | local real y 84 | local unit miner 85 | 86 | set index__player = 0 87 | loop 88 | set the_player = Player (index__player) 89 | 90 | if GetPlayerSlotState (the_player) == PLAYER_SLOT_STATE_PLAYING and Gem_Player__Is_Player (the_player) then 91 | set x = GetStartLocationX (index__player) 92 | set y = GetStartLocationY (index__player) 93 | set miner = CreateUnit (the_player, 'u000', x, y, bj_UNIT_FACING) 94 | set Gem_Player___MINER [index__player] = miner 95 | 96 | call UnitAddItem (miner, CreateItem ('gmi1', x, y)) 97 | call UnitAddItem (miner, CreateItem ('gmi2', x, y)) 98 | 99 | // Ensure that the player camera is set to the builder during 100 | // map initialization. This prevents a brief shift from the 101 | // middle of the map at game start. 102 | if the_player == GetLocalPlayer () then 103 | call SetCameraPosition (x, y) 104 | endif 105 | endif 106 | 107 | set index__player = index__player + 1 108 | exitwhen index__player >= Gem__MAXIMUM_PLAYERS 109 | endloop 110 | 111 | return false 112 | endfunction 113 | -------------------------------------------------------------------------------- /src/gem/quality.j: -------------------------------------------------------------------------------- 1 | // Gem Quality 2 | // =========== 3 | // 4 | // Manages the various gem quality levels. Sets up the default ones, but also 5 | // allows adding additional qualities. 6 | // 7 | // Depends 8 | // ------- 9 | // 10 | // - ID 11 | // - Table 12 | 13 | globals 14 | integer Gem_Quality___ID = ID__NULL 15 | 16 | integer Gem_Quality___Count = 0 17 | integer array Gem_Quality___Quality 18 | 19 | integer Gem_Quality__CHIPPED = ID__NULL 20 | integer Gem_Quality__FLAWED = ID__NULL 21 | integer Gem_Quality__NORMAL = ID__NULL 22 | integer Gem_Quality__FLAWLESS = ID__NULL 23 | integer Gem_Quality__PERFECT = ID__NULL 24 | integer Gem_Quality__GREAT = ID__NULL 25 | endglobals 26 | 27 | // Returns a `boolean` indicating whether the quality specified by 28 | // `quality_id` is registered. 29 | function Gem_Quality__Is_Quality takes integer quality_id returns boolean 30 | return HaveSavedInteger (Table, Gem_Quality___ID, quality_id) 31 | endfunction 32 | 33 | // Returns the `integer` count of the number of registered qualities. 34 | function Gem_Quality__Get_Count takes nothing returns integer 35 | return Gem_Quality___Count 36 | endfunction 37 | 38 | // Returns the `integer` ID for the specified `quality_index`. Returns 39 | // `ID__NULL` for invalid input. 40 | function Gem_Quality__Get_ID takes integer quality_index returns integer 41 | local integer quality_id 42 | 43 | set quality_id = Gem_Quality___Quality [quality_index] 44 | 45 | if quality_id == 0 then 46 | return ID__NULL 47 | else 48 | return quality_id 49 | endif 50 | endfunction 51 | 52 | // Returns the `integer` index for the specified `quality_id`. Returns `-1` 53 | // for invalid input. 54 | function Gem_Quality__Get_Index takes integer quality_id returns integer 55 | if not Gem_Quality__Is_Quality (quality_id) then 56 | return -1 57 | endif 58 | 59 | return LoadInteger (Table, Gem_Quality___ID, quality_id) 60 | endfunction 61 | 62 | // Returns an `integer` ID representing a newly allocated quality. 63 | function Gem_Quality___Allocate takes nothing returns integer 64 | local integer quality_index 65 | local integer quality_id 66 | 67 | set quality_index = Gem_Quality___Count 68 | set quality_id = ID () 69 | 70 | set Gem_Quality___Count = quality_index + 1 71 | call SaveInteger (Table, Gem_Quality___ID, quality_id, quality_index) 72 | set Gem_Quality___Quality [quality_index] = quality_id 73 | 74 | return quality_id 75 | endfunction 76 | 77 | function Gem_Quality__Initialize takes nothing returns boolean 78 | set Gem_Quality___ID = ID () 79 | 80 | // Declare qualities from low to high to ensure proper indices. 81 | set Gem_Quality__CHIPPED = Gem_Quality___Allocate () 82 | set Gem_Quality__FLAWED = Gem_Quality___Allocate () 83 | set Gem_Quality__NORMAL = Gem_Quality___Allocate () 84 | set Gem_Quality__FLAWLESS = Gem_Quality___Allocate () 85 | set Gem_Quality__PERFECT = Gem_Quality___Allocate () 86 | set Gem_Quality__GREAT = Gem_Quality___Allocate () 87 | 88 | return false 89 | endfunction 90 | -------------------------------------------------------------------------------- /src/gem/recipe.j: -------------------------------------------------------------------------------- 1 | // Gem Recipe 2 | // ========== 3 | 4 | globals 5 | constant hashtable Gem_Recipe___TABLE = Hashtable__New () 6 | 7 | constant integer Gem_Recipe___RESULT = -1 8 | constant integer Gem_Recipe___SIZE = -2 9 | endglobals 10 | 11 | function Gem_Recipe___Set_Size takes integer combination, integer size returns nothing 12 | call SaveInteger (Gem_Recipe___TABLE, combination, Gem_Recipe___SIZE, size) 13 | endfunction 14 | 15 | function Gem_Recipe__Get_Size takes integer combination returns integer 16 | return LoadInteger (Gem_Recipe___TABLE, combination, Gem_Recipe___SIZE) 17 | endfunction 18 | 19 | function Gem_Recipe__Has_Part takes integer combination, integer index returns boolean 20 | return HaveSavedInteger (Gem_Recipe___TABLE, combination, index) 21 | endfunction 22 | 23 | function Gem_Recipe___Add_Part takes integer combination, integer part returns nothing 24 | local integer index 25 | 26 | if combination == 0 or part == 0 then 27 | return 28 | endif 29 | 30 | set index = Gem_Recipe__Get_Size (combination) 31 | call Gem_Recipe___Set_Size (combination, index + 1) 32 | 33 | call SaveInteger (Gem_Recipe___TABLE, combination, index, part) 34 | endfunction 35 | 36 | function Gem_Recipe__Get_Part takes integer combination, integer index returns integer 37 | return LoadInteger (Gem_Recipe___TABLE, combination, index) 38 | endfunction 39 | 40 | function Gem_Recipe__Has_Combination takes integer part returns boolean 41 | return HaveSavedInteger (Gem_Recipe___TABLE, part, Gem_Recipe___RESULT) 42 | endfunction 43 | 44 | function Gem_Recipe___Set_Combination takes integer part, integer combination returns nothing 45 | if combination == 0 or part == 0 then 46 | return 47 | endif 48 | 49 | call SaveInteger (Gem_Recipe___TABLE, part, Gem_Recipe___RESULT, combination) 50 | endfunction 51 | 52 | function Gem_Recipe__Get_Combination takes integer part returns integer 53 | return LoadInteger (Gem_Recipe___TABLE, part, Gem_Recipe___RESULT) 54 | endfunction 55 | 56 | function Gem_Recipe__Register takes integer combination, integer A, integer B, integer C, integer D returns nothing 57 | call Gem_Recipe___Add_Part (combination, A) 58 | call Gem_Recipe___Set_Combination (A, combination) 59 | 60 | call Gem_Recipe___Add_Part (combination, B) 61 | call Gem_Recipe___Set_Combination (B, combination) 62 | 63 | call Gem_Recipe___Add_Part (combination, C) 64 | call Gem_Recipe___Set_Combination (C, combination) 65 | 66 | call Gem_Recipe___Add_Part (combination, D) 67 | call Gem_Recipe___Set_Combination (D, combination) 68 | endfunction 69 | -------------------------------------------------------------------------------- /src/gem/selection/downgrade.j: -------------------------------------------------------------------------------- 1 | // Gem Selection Downgrade 2 | // ======================= 3 | // 4 | // Depends 5 | // ------- 6 | // 7 | // - Color 8 | // - Gem Gems 9 | // - Gem Placement 10 | // - Gem Quality 11 | // - Gem Selection 12 | // - Gem Type 13 | 14 | globals 15 | constant integer Gem_Selection_Downgrade__ABILITY = 'A02G' 16 | endglobals 17 | 18 | function Gem_Selection_Downgrade___On_Finish takes nothing returns boolean 19 | local player the_player 20 | local unit the_unit 21 | local integer the_unit_type 22 | local integer index 23 | local integer quality_id 24 | 25 | set the_player = Gem_Placement__The_Player () 26 | 27 | set index = 1 28 | loop 29 | exitwhen not Gem_Selection__Has (the_player, index) 30 | 31 | set the_unit = Gem_Selection__Get (the_player, index) 32 | set the_unit_type = GetUnitTypeId (the_unit) 33 | 34 | if Gem_Gems__Is_Gem (the_unit_type) then 35 | set quality_id = Gem_Gems__Get_ID_Quality (the_unit_type) 36 | 37 | if quality_id != ID__NULL and quality_id != Gem_Quality__CHIPPED then 38 | call UnitAddAbility (the_unit, Gem_Selection_Downgrade__ABILITY) 39 | endif 40 | endif 41 | 42 | set index = index + 1 43 | endloop 44 | 45 | return false 46 | endfunction 47 | 48 | function Gem_Selection_Downgrade___Event takes nothing returns boolean 49 | local player the_player 50 | 51 | local unit original 52 | local integer original_type 53 | 54 | local unit replacement 55 | local integer replacement_type 56 | 57 | local integer quality_id 58 | local integer quality_index 59 | 60 | local integer type_id 61 | 62 | if GetSpellAbilityId () != Gem_Selection_Downgrade__ABILITY then 63 | return false 64 | endif 65 | 66 | set the_player = GetTriggerPlayer () 67 | 68 | set original = GetTriggerUnit () 69 | set original_type = GetUnitTypeId (original) 70 | 71 | set quality_id = Gem_Gems__Get_ID_Quality (original_type) 72 | set type_id = Gem_Gems__Get_ID_Type (original_type) 73 | 74 | set quality_index = Gem_Quality__Get_Index (quality_id) - 1 75 | 76 | set quality_id = Gem_Quality__Get_ID (quality_index) 77 | set replacement_type = Gem_Gems__Get_Unit_Type (type_id, quality_id) 78 | 79 | call ShowUnit (original, false) 80 | call Gem_Ground_Textures__Prepare () 81 | set replacement = CreateUnit (the_player, replacement_type, GetUnitX (original), GetUnitY (original), GetUnitFacing (original)) 82 | call Gem_Ground_Textures__Register (replacement) 83 | call RemoveUnit (original) 84 | 85 | if type_id == Gem_Type__OPAL then 86 | call SetUnitAbilityLevel (replacement, 'S008', quality_index + 1) 87 | endif 88 | 89 | call DisplayTextToPlayer (the_player, 0.00, 0.00, Color ("33ff33", GetUnitName (replacement) + " has been created!!")) 90 | 91 | call Gem_Selection__Finalize (replacement, original) 92 | 93 | return false 94 | endfunction 95 | 96 | function Gem_Selection_Downgrade__Initialize takes nothing returns boolean 97 | call Gem_Placement__On_Finish (Condition (function Gem_Selection_Downgrade___On_Finish)) 98 | call Gem_Selection__Register_Event (Condition (function Gem_Selection_Downgrade___Event)) 99 | 100 | return false 101 | endfunction 102 | -------------------------------------------------------------------------------- /src/gem/selection/initialize.j: -------------------------------------------------------------------------------- 1 | function Gem_Selection__Initialize takes nothing returns boolean 2 | local trigger rule = CreateTrigger () 3 | local player whom 4 | local integer whom_id = -1 5 | 6 | call Gem_Placement__On_Start (Condition (function Gem_Selection___On_Start)) 7 | call Gem_Placement__On_Placement (Condition (function Gem_Selection___On_Placement)) 8 | 9 | call Gem_Selection_Keep__Initialize () 10 | call Gem_Selection_Downgrade__Initialize () 11 | call Gem_Selection_Combine__Initialize (rule) 12 | call Gem_Selection_Slate__Initialize (rule) 13 | call Gem_Selection_Special__Initialize () 14 | 15 | call Gem_Placement__On_Finish (Condition (function Gem_Selection___On_Finish)) 16 | 17 | loop 18 | set whom_id = whom_id + 1 19 | exitwhen whom_id >= Gem__MAXIMUM_PLAYERS 20 | 21 | set whom = Player (whom_id) 22 | call TriggerRegisterPlayerUnitEvent (Gem_Selection___TRIGGER, whom, EVENT_PLAYER_UNIT_SPELL_CAST, null) 23 | call TriggerRegisterPlayerUnitEvent (rule, whom, EVENT_PLAYER_UNIT_ISSUED_ORDER, null) 24 | endloop 25 | 26 | return false 27 | endfunction 28 | -------------------------------------------------------------------------------- /src/gem/selection/keep.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Gem_Selection_Keep__ABILITY = 'A009' 3 | endglobals 4 | 5 | function Gem_Selection_Keep___On_Finish takes nothing returns boolean 6 | local player the_player 7 | local unit the_unit 8 | local integer index 9 | 10 | set the_player = Gem_Placement__The_Player () 11 | 12 | set index = 1 13 | loop 14 | exitwhen not Gem_Selection__Has (the_player, index) 15 | set the_unit = Gem_Selection__Get (the_player, index) 16 | 17 | call UnitAddAbility (the_unit, Gem_Selection_Keep__ABILITY) 18 | 19 | set index = index + 1 20 | endloop 21 | 22 | return false 23 | endfunction 24 | 25 | function Gem_Selection_Keep___Event takes nothing returns boolean 26 | local player the_player 27 | local unit the_unit 28 | 29 | if GetSpellAbilityId () != Gem_Selection_Keep__ABILITY then 30 | return false 31 | endif 32 | 33 | set the_player = GetTriggerPlayer () 34 | set the_unit = GetTriggerUnit () 35 | 36 | call DisplayTextToPlayer (the_player, 0.00, 0.00, Color ("66ffff", GetUnitName (the_unit) + " has been chosen as your gem this round.")) 37 | 38 | call UnitRemoveAbility (the_unit, Gem_Selection_Keep__ABILITY) 39 | call UnitRemoveAbility (the_unit, Gem_Selection_Downgrade__ABILITY) 40 | call UnitRemoveAbility (the_unit, Gem_Selection_Combine__X2_ID) 41 | call UnitRemoveAbility (the_unit, Gem_Selection_Combine__X3_ID) 42 | call UnitRemoveAbility (the_unit, Gem_Selection_Combine__X4_ID) 43 | call UnitRemoveAbility (the_unit, Gem_Selection_Slate__KEEP_ID) 44 | call UnitRemoveAbility (the_unit, Gem_Selection_Slate__COMBINE_ID) 45 | call UnitRemoveAbility (the_unit, Gem_Selection_Special__ABILITY) 46 | 47 | call Gem_Selection__Finalize (the_unit, null) 48 | 49 | return false 50 | endfunction 51 | 52 | function Gem_Selection_Keep__Initialize takes nothing returns boolean 53 | call Gem_Placement__On_Finish (Condition (function Gem_Selection_Keep___On_Finish)) 54 | call Gem_Selection__Register_Event (Condition (function Gem_Selection_Keep___Event)) 55 | 56 | return false 57 | endfunction 58 | -------------------------------------------------------------------------------- /src/gem/selection/slate/marker.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant string Gem_Selection_Slate_Marker___SFX = "Abilities\\Spells\\Other\\Silence\\SilenceAreaBirth.mdl" 3 | 4 | constant real Gem_Selection_Slate_Marker___PERIOD = 0.9 5 | 6 | integer array Gem_Selection_Slate_Marker___Runners 7 | integer array Gem_Selection_Slate_Marker___Indices 8 | effect array Gem_Selection_Slate_Marker___Markers 9 | endglobals 10 | 11 | function Gem_Selection_Slate_Marker___SFX takes unit which returns nothing 12 | local integer index = Unit_Indexer__Unit_Index (which) 13 | 14 | call DestroyEffect (Gem_Selection_Slate_Marker___Markers [index]) 15 | set Gem_Selection_Slate_Marker___Markers [index] = AddSpecialEffect (Gem_Selection_Slate_Marker___SFX, GetUnitX (which), GetUnitY (which)) 16 | endfunction 17 | 18 | function Gem_Selection_Slate_Marker___Effect takes nothing returns boolean 19 | local integer runner = Run__Scheduled () 20 | local integer index = Gem_Selection_Slate_Marker___Indices [runner] 21 | local unit which = Unit_Indexer__Unit_By_Index (index) 22 | 23 | call Gem_Selection_Slate_Marker___SFX (which) 24 | 25 | return true 26 | endfunction 27 | 28 | function Gem_Selection_Slate_Marker__Attach takes unit which returns nothing 29 | local integer index = Unit_Indexer__Unit_Index (which) 30 | local integer runner = Gem_Selection_Slate_Marker___Runners [index] 31 | 32 | if runner != Run__NULL then 33 | return 34 | endif 35 | 36 | set runner = Run__Every (Gem_Selection_Slate_Marker___PERIOD, function Gem_Selection_Slate_Marker___Effect) 37 | set Gem_Selection_Slate_Marker___Indices [runner] = index 38 | set Gem_Selection_Slate_Marker___Runners [index] = runner 39 | call Gem_Selection_Slate_Marker___SFX (which) 40 | endfunction 41 | 42 | function Gem_Selection_Slate_Marker__Detach takes unit which returns nothing 43 | local integer index = Unit_Indexer__Unit_Index (which) 44 | local integer runner = Gem_Selection_Slate_Marker___Runners [index] 45 | 46 | if runner == Run__NULL then 47 | return 48 | endif 49 | 50 | call Run__Cancel (runner) 51 | set Gem_Selection_Slate_Marker___Runners [index] = Run__NULL 52 | set Gem_Selection_Slate_Marker___Indices [runner] = 0 53 | 54 | call DestroyEffect (Gem_Selection_Slate_Marker___Markers [index]) 55 | set Gem_Selection_Slate_Marker___Markers [index] = null 56 | endfunction 57 | 58 | function Gem_Selection_Slate_Marker___On_Leave takes nothing returns boolean 59 | call Gem_Selection_Slate_Marker__Detach (Unit_Event__The_Unit ()) 60 | 61 | return false 62 | endfunction 63 | 64 | function Gem_Selection_Slate_Marker___On_Death takes nothing returns boolean 65 | call Gem_Selection_Slate_Marker__Detach (Unit_Event__The_Unit ()) 66 | 67 | return false 68 | endfunction 69 | 70 | function Gem_Selection_Slate_Marker__Initialize takes nothing returns boolean 71 | call Unit_Event__On_Leave (Condition (function Gem_Selection_Slate_Marker___On_Leave)) 72 | call Unit_Event__On_Death (Condition (function Gem_Selection_Slate_Marker___On_Death)) 73 | 74 | return false 75 | endfunction 76 | -------------------------------------------------------------------------------- /src/gem/slate.j: -------------------------------------------------------------------------------- 1 | // Gem Slate 2 | // ========= 3 | 4 | globals 5 | constant integer Gem_Slate__HOLD = 'n002' 6 | constant integer Gem_Slate__AIR = 'n000' 7 | constant integer Gem_Slate__ANCIENT = 'n003' 8 | 9 | constant integer Gem_Slate__OPAL_VEIN = 'n004' 10 | constant integer Gem_Slate__SLOW = 'n001' 11 | constant integer Gem_Slate__WRAITH = 'n005' 12 | 13 | constant integer Gem_Slate__SPELL = 'n009' 14 | constant integer Gem_Slate__POISON = 'n008' 15 | constant integer Gem_Slate__ELDER = 'n00A' 16 | 17 | constant integer Gem_Slate__DAMAGE = 'n00C' 18 | constant integer Gem_Slate__RANGE = 'n00E' 19 | constant integer Gem_Slate__VIPER = 'n00F' 20 | 21 | boolean array Gem_Slate___Is_Slate 22 | string array Gem_Slate___Name 23 | integer array Gem_Slate___Normal 24 | integer array Gem_Slate___Flawed_A 25 | integer array Gem_Slate___Flawed_B 26 | integer array Gem_Slate___Flawed_C 27 | endglobals 28 | 29 | // Convert the unit type referenced by `slate` into a more appropriate 30 | // `integer` ID usable within an array (i.e. of the range `[0, 15]`). 31 | function Gem_Slate___ID takes integer slate returns integer 32 | return slate - 'n000' 33 | endfunction 34 | 35 | function Gem_Slate__Is_Slate takes integer slate returns boolean 36 | return Gem_Slate___Is_Slate [Gem_Slate___ID (slate)] 37 | endfunction 38 | 39 | function Gem_Slate__Name takes integer slate returns string 40 | return Gem_Slate___Name [Gem_Slate___ID (slate)] 41 | endfunction 42 | 43 | function Gem_Slate__Size takes integer slate returns integer 44 | if Gem_Slate__Get_Flawed_C (slate) == 0 then 45 | return 2 46 | else 47 | return 3 48 | endif 49 | endfunction 50 | 51 | function Gem_Slate__Get_Normal takes integer slate returns integer 52 | return Gem_Slate___Normal [Gem_Slate___ID (slate)] 53 | endfunction 54 | 55 | function Gem_Slate__Get_Flawed_A takes integer slate returns integer 56 | return Gem_Slate___Flawed_A [Gem_Slate___ID (slate)] 57 | endfunction 58 | 59 | function Gem_Slate__Get_Flawed_B takes integer slate returns integer 60 | return Gem_Slate___Flawed_B [Gem_Slate___ID (slate)] 61 | endfunction 62 | 63 | function Gem_Slate__Get_Flawed_C takes integer slate returns integer 64 | return Gem_Slate___Flawed_C [Gem_Slate___ID (slate)] 65 | endfunction 66 | -------------------------------------------------------------------------------- /src/gem/slate/damage.j: -------------------------------------------------------------------------------- 1 | // # Gem Slate: Damage 2 | 3 | function Gem_Slate___Damage takes nothing returns boolean 4 | local unit attacker 5 | local unit victim 6 | local player owner 7 | local texttag tag 8 | local integer damage 9 | local real x 10 | local real y 11 | 12 | set attacker = GetAttacker () 13 | 14 | if GetUnitTypeId (attacker) == 'n00C' then 15 | set victim = GetTriggerUnit () 16 | set owner = GetOwningPlayer (attacker) 17 | set x = GetUnitX (attacker) 18 | set y = GetUnitY (attacker) 19 | 20 | call DestroyEffect (AddSpecialEffectTarget ("Abilities\\Spells\\Human\\Invisibility\\InvisibilityTarget.mdl", victim, "chest")) 21 | call DestroyEffect (AddSpecialEffect ("Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl", x, y)) 22 | 23 | set damage = Unit_User_Data__Get (attacker) * 10 + 256 24 | call Unit_Damage__Is_Code () 25 | call UnitDamageTarget (attacker, victim, damage, true, true, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS) 26 | 27 | set tag = CreateTextTag () 28 | call SetTextTagText (tag, I2S (damage) + " Damage!", 0.023) 29 | call SetTextTagPos (tag, x - 75.00, y, 0.00) 30 | call SetTextTagColor (tag, GetRandomInt (0, 255), GetRandomInt (0, 255), GetRandomInt (0, 255), 255) 31 | call SetTextTagPermanent (tag, false) 32 | call SetTextTagLifespan (tag, 1.50) 33 | call SetTextTagFadepoint (tag, 1.00) 34 | call SetTextTagVisibility (tag, true) 35 | 36 | call Unit_Disarm__Apply (attacker, 1.00) 37 | endif 38 | 39 | return false 40 | endfunction 41 | 42 | function Gem_Slate___Initialize_Damage takes nothing returns nothing 43 | local trigger the_trigger 44 | local integer index 45 | 46 | set the_trigger = CreateTrigger () 47 | 48 | set index = 11 49 | loop 50 | call TriggerRegisterPlayerUnitEvent (the_trigger, Player (index), EVENT_PLAYER_UNIT_ATTACKED, null) 51 | set index = index + 1 52 | exitwhen index > 18 53 | endloop 54 | 55 | call TriggerAddCondition (the_trigger, Condition (function Gem_Slate___Damage)) 56 | endfunction 57 | -------------------------------------------------------------------------------- /src/gem/slate/elder.j: -------------------------------------------------------------------------------- 1 | function Gem_Slate_Elder__Initialize takes nothing returns nothing 2 | call Preload__Ability ('A05Z') // Fan of Knives 3 | call Preload__Ability ('A05X') // Thunder Clap 4 | call Preload__Ability ('A05W') // Frost Armor 5 | call Preload__Ability ('A063') // Forked Lightning 6 | endfunction 7 | -------------------------------------------------------------------------------- /src/gem/slate/hold.j: -------------------------------------------------------------------------------- 1 | // # Gem Slate: Hold 2 | 3 | globals 4 | group Gem_Slate___Hold_Group = CreateGroup () 5 | unit Gem_Slate___Hold_Unit = null 6 | endglobals 7 | 8 | function Gem_Slate___Hold_Taunt takes nothing returns boolean 9 | local unit the_unit 10 | local integer the_unit_type 11 | local real x 12 | local real y 13 | 14 | set the_unit = GetFilterUnit () 15 | set the_unit_type = GetUnitTypeId (the_unit) 16 | 17 | if not Gem_Player__Is_Monster (GetOwningPlayer (the_unit)) and the_unit_type != 'u000' and the_unit_type != Gem_Slate__HOLD and the_unit_type != Gem_Slate__ANCIENT then 18 | call IssueTargetOrder (the_unit, "attack", Gem_Slate___Hold_Unit) 19 | endif 20 | 21 | return false 22 | endfunction 23 | 24 | function Gem_Slate___Hold takes nothing returns boolean 25 | local unit attacker 26 | local unit victim 27 | local texttag tag 28 | local integer damage 29 | local real x 30 | local real y 31 | 32 | set attacker = GetAttacker () 33 | set victim = GetTriggerUnit () 34 | 35 | if GetUnitTypeId (attacker) != 'n002' then 36 | return false 37 | endif 38 | 39 | call BlzUnitInterruptAttack (attacker) 40 | 41 | if Unit_Stun__Is_Stunned (victim) then 42 | return false 43 | endif 44 | 45 | if Unit_Stun__Apply (victim, 1.50) then 46 | set Gem_Slate___Hold_Unit = victim 47 | call GroupEnumUnitsInRange (Gem_Slate___Hold_Group, GetUnitX (victim), GetUnitY (victim), 600.00, Filter (function Gem_Slate___Hold_Taunt)) 48 | set Gem_Slate___Hold_Unit = null 49 | 50 | set x = GetUnitX (attacker) 51 | set y = GetUnitY (attacker) 52 | 53 | call DestroyEffect (AddSpecialEffectTarget ("Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl", victim, "chest")) 54 | call DestroyEffect (AddSpecialEffect ("Abilities\\Spells\\Undead\\ReplenishHealth\\ReplenishHealthCasterOverhead.mdl", x, y)) 55 | 56 | set damage = Unit_User_Data__Get (attacker) * 20 + 160 57 | call Unit_Damage__Is_Code () 58 | call UnitDamageTarget (attacker, victim, damage, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS) 59 | 60 | set tag = CreateTextTag () 61 | call SetTextTagText (tag, I2S (damage) + " Damage!", 0.023) 62 | call SetTextTagPos (tag, x, y, 0.00) 63 | call SetTextTagColor (tag, 0, 255, 0, 255) 64 | call SetTextTagPermanent (tag, false) 65 | call SetTextTagLifespan (tag, 3.00) 66 | call SetTextTagFadepoint (tag, 2.50) 67 | call SetTextTagVisibility (tag, true) 68 | 69 | call Unit_Disarm__Apply (attacker, 3.50) 70 | endif 71 | 72 | return false 73 | endfunction 74 | 75 | function Gem_Slate___Initialize_Hold takes nothing returns nothing 76 | local trigger the_trigger 77 | local integer index 78 | 79 | set the_trigger = CreateTrigger () 80 | 81 | set index = 11 82 | loop 83 | call TriggerRegisterPlayerUnitEvent (the_trigger, Player (index), EVENT_PLAYER_UNIT_ATTACKED, null) 84 | set index = index + 1 85 | exitwhen index > 18 86 | endloop 87 | 88 | call TriggerAddCondition (the_trigger, Condition (function Gem_Slate___Hold)) 89 | endfunction 90 | -------------------------------------------------------------------------------- /src/gem/slate/poison.j: -------------------------------------------------------------------------------- 1 | // # Gem Slate: Poison 2 | 3 | function Gem_Slate___Poison takes nothing returns boolean 4 | local unit attacker 5 | local unit victim 6 | local integer level 7 | local boolean is_poisoned 8 | 9 | set attacker = GetAttacker () 10 | 11 | if GetUnitTypeId (attacker) == 'n008' then 12 | set is_poisoned = false 13 | 14 | if GetUnitState (attacker, UNIT_STATE_MANA) >= 5.0 then 15 | set victim = GetTriggerUnit () 16 | set level = IMinBJ (Unit_User_Data__Get (attacker) / 10 + 1, 11) 17 | 18 | call UnitAddAbility (attacker, 'A05N') 19 | call SetUnitAbilityLevel (attacker, 'A05N', level) 20 | set is_poisoned = IssueTargetOrder (attacker, ORDER_SHADOWSTRIKE, victim) 21 | call UnitRemoveAbility (attacker, 'A05N') 22 | endif 23 | 24 | if is_poisoned then 25 | call DestroyEffect (AddSpecialEffect ("Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl", GetUnitX (attacker), GetUnitY (attacker))) 26 | else 27 | call IssueImmediateOrder (attacker, "stop") 28 | endif 29 | endif 30 | 31 | return false 32 | endfunction 33 | 34 | function Gem_Slate___Initialize_Poison takes nothing returns nothing 35 | local trigger the_trigger 36 | local integer index 37 | 38 | set the_trigger = CreateTrigger () 39 | 40 | set index = 11 41 | loop 42 | call TriggerRegisterPlayerUnitEvent (the_trigger, Player (index), EVENT_PLAYER_UNIT_ATTACKED, null) 43 | set index = index + 1 44 | exitwhen index > 18 45 | endloop 46 | 47 | call TriggerAddCondition (the_trigger, Condition (function Gem_Slate___Poison)) 48 | endfunction 49 | 50 | function Gem_Slate_Poison__Initialize takes nothing returns nothing 51 | call Preload__Ability ('A05N') // Shadow Strike 52 | endfunction 53 | -------------------------------------------------------------------------------- /src/gem/slate/spell.j: -------------------------------------------------------------------------------- 1 | function Gem_Slate_Spell__Initialize takes nothing returns nothing 2 | call Preload__Ability ('A05R') // Fan of Knives 3 | call Preload__Ability ('A05S') // Forked Lightning 4 | call Preload__Ability ('A05U') // Carrion Swarm 5 | endfunction 6 | -------------------------------------------------------------------------------- /src/gem/slate/viper.j: -------------------------------------------------------------------------------- 1 | function Gem_Slate_Viper___Register_SFX takes nothing returns nothing 2 | local string id = "viper" 3 | local string sfx = "Abilities\\Spells\\Undead\\ReplenishMana\\ReplenishManaCaster.mdl" 4 | local string attach = "head" 5 | local real period = 0.20 6 | local real duration = 1.035 7 | 8 | call Gem_Immolation__Register_SFX (id, sfx, attach, period, duration) 9 | endfunction 10 | 11 | function Gem_Slate_Viper___Register takes unit which returns nothing 12 | local string id = "viper" 13 | local real radius = 400.0 14 | local real period = 0.20 15 | local real damage = 10.0 16 | 17 | call Gem_Immolation__Register (which, id, radius, period, damage) 18 | endfunction 19 | 20 | function Gem_Slate_Viper___Enter takes nothing returns boolean 21 | local unit which = Unit_Event__The_Unit () 22 | local integer id = GetUnitTypeId (which) 23 | 24 | if id == Gem_Slate__VIPER then 25 | call Gem_Slate_Viper___Register (which) 26 | endif 27 | 28 | return true 29 | endfunction 30 | 31 | function Gem_Slate_Viper__Initialize takes nothing returns nothing 32 | local boolexpr enter 33 | 34 | call Gem_Slate_Viper___Register_SFX () 35 | 36 | set enter = Condition (function Gem_Slate_Viper___Enter) 37 | call Unit_Event__On_Enter (enter) 38 | endfunction 39 | -------------------------------------------------------------------------------- /src/gem/special.j: -------------------------------------------------------------------------------- 1 | // Gem Special 2 | // =========== 3 | 4 | globals 5 | constant integer Gem_Special__MALACHITE_1 = 'h03X' 6 | constant integer Gem_Special__MALACHITE_2 = 'h03Y' 7 | constant integer Gem_Special__MALACHITE_3 = 'h03Z' 8 | 9 | constant integer Gem_Special__SILVER_1 = 'h01A' 10 | constant integer Gem_Special__SILVER_2 = 'h02O' 11 | constant integer Gem_Special__SILVER_3 = 'h033' 12 | 13 | constant integer Gem_Special__STAR_RUBY_1 = 'h016' 14 | constant integer Gem_Special__STAR_RUBY_2 = 'h02M' 15 | constant integer Gem_Special__STAR_RUBY_3 = 'e006' 16 | 17 | constant integer Gem_Special__JADE_1 = 'h018' 18 | constant integer Gem_Special__JADE_2 = 'h02L' 19 | constant integer Gem_Special__JADE_3 = 'h035' 20 | 21 | constant integer Gem_Special__RED_CRYSTAL_1 = 'h029' 22 | constant integer Gem_Special__RED_CRYSTAL_2 = 'h02J' 23 | constant integer Gem_Special__RED_CRYSTAL_3 = 'h02Q' 24 | 25 | constant integer Gem_Special__DARK_EMERALD_1 = 'h01N' 26 | constant integer Gem_Special__DARK_EMERALD_2 = 'h02V' 27 | 28 | constant integer Gem_Special__GOLD_1 = 'h01B' 29 | constant integer Gem_Special__GOLD_2 = 'h02W' 30 | 31 | constant integer Gem_Special__URANIUM_1 = 'h019' 32 | constant integer Gem_Special__URANIUM_2 = 'h02N' 33 | 34 | constant integer Gem_Special__PINK_DIAMOND_1 = 'h017' 35 | constant integer Gem_Special__PINK_DIAMOND_2 = 'h02P' 36 | 37 | constant integer Gem_Special__PARAIBA_TOURMALINE_1 = 'h040' 38 | constant integer Gem_Special__PARAIBA_TOURMALINE_2 = 'h041' 39 | 40 | constant integer Gem_Special__BLACK_OPAL_1 = 'h015' 41 | constant integer Gem_Special__BLACK_OPAL_2 = 'h02K' 42 | 43 | constant integer Gem_Special__BLOOD_STONE_1 = 'h01O' 44 | constant integer Gem_Special__BLOOD_STONE_2 = 'h02U' 45 | 46 | constant integer Gem_Special__YELLOW_SAPPHIRE_1 = 'h014' 47 | constant integer Gem_Special__YELLOW_SAPPHIRE_2 = 'h02R' 48 | 49 | constant integer Gem_Special__STONE_OF_BRYVX = 'h04A' 50 | 51 | integer Gem_Special___Upgrades = Node__NULL 52 | endglobals 53 | -------------------------------------------------------------------------------- /src/gem/special/jade.j: -------------------------------------------------------------------------------- 1 | // # Jade 2 | 3 | function Gem_Special___Jade_Tag takes unit the_unit, string message, integer red, integer green, integer blue returns nothing 4 | local texttag tag 5 | 6 | if the_unit == null then 7 | return 8 | endif 9 | 10 | set tag = CreateTextTag () 11 | call SetTextTagPos (tag, GetUnitX (the_unit), GetUnitY (the_unit), 0.00) 12 | call SetTextTagPermanent (tag, false) 13 | call SetTextTagLifespan (tag, 2.00) 14 | call SetTextTagFadepoint (tag, 1.50) 15 | call SetTextTagVisibility (tag, true) 16 | call SetTextTagText (tag, message, 0.023) 17 | call SetTextTagColor (tag, red, green, blue, 255) 18 | endfunction 19 | 20 | function Gem_Special___Jade takes nothing returns boolean 21 | local string kind = Unit_Damage__Kind () 22 | 23 | local unit source = GetEventDamageSource () 24 | local unit target = GetTriggerUnit () 25 | 26 | local unit attacker 27 | local unit victim 28 | local player owner 29 | local integer player_index 30 | local integer roll 31 | local integer gold 32 | 33 | set Label = "Gem_Special_Jade" 34 | 35 | if kind != "attack" then 36 | return true 37 | endif 38 | 39 | set attacker = source 40 | set victim = target 41 | 42 | if GetUnitTypeId (attacker) == 'h035' then 43 | set owner = GetOwningPlayer (attacker) 44 | set roll = GetRandomInt (1, 100) 45 | 46 | // Gold: 47 | if roll == 1 then 48 | set player_index = GetPlayerId (owner) 49 | set gold = udg_RLevel [player_index + 1] / 2 50 | set udg_CountJadeMoney [player_index + 1] = udg_CountJadeMoney [player_index + 1] + gold 51 | 52 | call SetPlayerState (owner, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState (owner, PLAYER_STATE_RESOURCE_GOLD) + gold) 53 | call Gem_Special___Jade_Tag (attacker, "+" + I2S (gold) + " Gold!", 255, 255, 0) 54 | 55 | // Stun: 56 | elseif roll == 2 and not Unit_Stun__Is_Stunned (victim) then 57 | if not Unit_Stun__Apply (victim, 2.0) then 58 | return true 59 | endif 60 | 61 | call DestroyEffect (AddSpecialEffectTarget ("Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl", victim, "chest")) 62 | call Gem_Special___Jade_Tag (attacker, "Stun Hit!", 0, 255, 255) 63 | endif 64 | endif 65 | 66 | return true 67 | endfunction 68 | 69 | function Gem_Special___Initialize_Jade takes nothing returns nothing 70 | call Unit_Damage__On_Damage (function Gem_Special___Jade) 71 | endfunction 72 | -------------------------------------------------------------------------------- /src/gem/special/red-crystal.j: -------------------------------------------------------------------------------- 1 | function Gem_Special_Red_Crystal___Register_SFX takes nothing returns nothing 2 | local string id = "red crystal" 3 | local string sfx = "Abilities\\Spells\\Demon\\DemonBoltImpact\\DemonBoltImpact.mdl" 4 | local string attach = "chest" 5 | local real period = 1.0 6 | 7 | call Gem_Immolation__Register_SFX (id, sfx, attach, period) 8 | endfunction 9 | 10 | function Gem_Special_Red_Crystal___Register takes unit which returns nothing 11 | local string id = "red crystal" 12 | local real radius = 1500.0 13 | local real period = 0.20 14 | local real damage = 10.0 15 | 16 | call Gem_Immolation__Register (which, id, radius, period, damage) 17 | endfunction 18 | 19 | function Gem_Special_Red_Crystal___Enter takes nothing returns boolean 20 | local unit which = Unit_Event__The_Unit () 21 | local integer id = GetUnitTypeId (which) 22 | 23 | if id == Gem_Special__RED_CRYSTAL_3 then 24 | call Gem_Special_Red_Crystal___Register (which) 25 | endif 26 | 27 | return true 28 | endfunction 29 | 30 | function Gem_Special_Red_Crystal___Upgrade takes nothing returns boolean 31 | local unit which = GetTriggerUnit () 32 | local integer id = GetUnitTypeId (which) 33 | local integer kills 34 | local integer level 35 | 36 | if id == Gem_Special__RED_CRYSTAL_3 then 37 | call Gem_Special_Red_Crystal___Register (which) 38 | set kills = Unit_User_Data__Get (which) 39 | set level = IMinBJ (10, kills / 10) + 1 40 | call SetUnitAbilityLevel (which, 'A01H', level) 41 | endif 42 | 43 | return true 44 | endfunction 45 | 46 | function Gem_Special_Red_Crystal___Kill takes nothing returns nothing 47 | local unit killer = GetKillingUnit () 48 | local integer id = GetUnitTypeId (killer) 49 | local integer kills 50 | 51 | if id != Gem_Special__RED_CRYSTAL_3 then 52 | return 53 | endif 54 | 55 | set kills = Unit_User_Data__Get (killer) 56 | 57 | if kills <= 100 and ModuloInteger (kills, 10) == 0 then 58 | call IncUnitAbilityLevel (killer, 'A01H') 59 | endif 60 | endfunction 61 | 62 | function Gem_Special_Red_Crystal__Initialize takes nothing returns nothing 63 | local boolexpr enter 64 | local trigger upgrade 65 | 66 | call Gem_Special_Red_Crystal___Register_SFX () 67 | 68 | set enter = Condition (function Gem_Special_Red_Crystal___Enter) 69 | call Unit_Event__On_Enter (enter) 70 | 71 | set upgrade = Trigger__New () 72 | call Trigger__Try (upgrade, function Gem_Special_Red_Crystal___Upgrade) 73 | call TriggerRegisterAnyUnitEventBJ (upgrade, EVENT_PLAYER_UNIT_UPGRADE_FINISH) 74 | endfunction 75 | -------------------------------------------------------------------------------- /src/gem/special/star-ruby.j: -------------------------------------------------------------------------------- 1 | function Gem_Special_Star_Ruby___Register_SFX takes nothing returns nothing 2 | local string id = "star ruby" 3 | local string sfx = "Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl" 4 | local string attach = "head" 5 | local real period = 0.290 6 | 7 | call Gem_Immolation__Register_SFX (id, sfx, attach, period) 8 | endfunction 9 | 10 | function Gem_Special_Star_Ruby___Register takes unit which returns nothing 11 | local string id = "star ruby" 12 | local real radius 13 | local real period = 0.25 14 | local real damage 15 | 16 | if GetUnitTypeId (which) == Gem_Special__STAR_RUBY_1 then 17 | set damage = 7.5 18 | set radius = 265.0 19 | elseif GetUnitTypeId (which) == Gem_Special__STAR_RUBY_2 then 20 | set damage = 10.0 21 | set radius = 500.0 22 | else 23 | return 24 | endif 25 | 26 | call Gem_Immolation__Deregister (which) 27 | call Gem_Immolation__Register (which, id, radius, period, damage) 28 | endfunction 29 | 30 | function Gem_Special_Star_Ruby___Enter takes nothing returns boolean 31 | local unit which = Unit_Event__The_Unit () 32 | local integer id = GetUnitTypeId (which) 33 | 34 | if id == Gem_Special__STAR_RUBY_1 then 35 | call Gem_Special_Star_Ruby___Register (which) 36 | elseif id == Gem_Special__STAR_RUBY_2 then 37 | call Gem_Special_Star_Ruby___Register (which) 38 | endif 39 | 40 | return true 41 | endfunction 42 | 43 | function Gem_Special_Star_Ruby___Upgrade takes nothing returns boolean 44 | local unit which = GetTriggerUnit () 45 | local integer id = GetUnitTypeId (which) 46 | local integer kills 47 | local integer level 48 | 49 | if id == Gem_Special__STAR_RUBY_2 then 50 | call Gem_Special_Star_Ruby___Register (which) 51 | elseif id == Gem_Special__STAR_RUBY_3 then 52 | call Gem_Immolation__Deregister (which) 53 | set kills = Unit_User_Data__Get (which) 54 | set level = IMinBJ (10, kills / 10) + 1 55 | call SetUnitAbilityLevel (which, 'A02F', level) 56 | endif 57 | 58 | return true 59 | endfunction 60 | 61 | function Gem_Special_Star_Ruby__Initialize takes nothing returns nothing 62 | local boolexpr enter 63 | local trigger upgrade 64 | 65 | call Gem_Special_Star_Ruby___Register_SFX () 66 | 67 | set enter = Condition (function Gem_Special_Star_Ruby___Enter) 68 | call Unit_Event__On_Enter (enter) 69 | 70 | set upgrade = Trigger__New () 71 | call Trigger__Try (upgrade, function Gem_Special_Star_Ruby___Upgrade) 72 | call TriggerRegisterAnyUnitEventBJ (upgrade, EVENT_PLAYER_UNIT_UPGRADE_FINISH) 73 | endfunction 74 | -------------------------------------------------------------------------------- /src/gem/special/tourmaline.j: -------------------------------------------------------------------------------- 1 | function Gem_Special_Tourmaline__Initialize takes nothing returns nothing 2 | call Preload__Ability ('A03J') // Frost Nova 3 | call Preload__Ability ('A03N') // Frost Nova 4 | endfunction 5 | -------------------------------------------------------------------------------- /src/gem/special/uranium.j: -------------------------------------------------------------------------------- 1 | function Gem_Special_Uranium___Register_SFX takes nothing returns nothing 2 | local string id = "uranium" 3 | local string sfx = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" 4 | local string attach = "head" 5 | local real period = 1.0 6 | 7 | call Gem_Immolation__Register_SFX (id, sfx, attach, period) 8 | endfunction 9 | 10 | function Gem_Special_Uranium___Register takes unit which returns nothing 11 | local string id = "uranium" 12 | local real radius = 500.0 13 | local real period = 0.10 14 | local real damage = 20.0 15 | 16 | call Gem_Immolation__Register (which, id, radius, period, damage) 17 | endfunction 18 | 19 | function Gem_Special_Uranium___Enter takes nothing returns boolean 20 | local unit which = Unit_Event__The_Unit () 21 | local integer id = GetUnitTypeId (which) 22 | 23 | if id == Gem_Special__URANIUM_1 then 24 | call Gem_Special_Uranium___Register (which) 25 | elseif id == Gem_Special__URANIUM_2 then 26 | call Gem_Special_Uranium___Register (which) 27 | endif 28 | 29 | return true 30 | endfunction 31 | 32 | function Gem_Special_Uranium___Upgrade takes nothing returns boolean 33 | local unit which = GetTriggerUnit () 34 | local integer id = GetUnitTypeId (which) 35 | local integer kills 36 | local integer level 37 | 38 | if id == Gem_Special__URANIUM_2 then 39 | set kills = Unit_User_Data__Get (which) 40 | set level = IMinBJ (10, kills / 10) + 1 41 | call SetUnitAbilityLevel (which, 'A0U0', level) 42 | endif 43 | 44 | return true 45 | endfunction 46 | 47 | function Gem_Special_Uranium___Combine takes unit which returns nothing 48 | local integer id = GetUnitTypeId (which) 49 | local integer kills 50 | local integer skill 51 | local integer level 52 | 53 | if id == Gem_Special__URANIUM_1 then 54 | set skill = 'A00W' 55 | elseif id == Gem_Special__URANIUM_2 then 56 | set skill = 'A0U0' 57 | else 58 | return 59 | endif 60 | 61 | set kills = Unit_User_Data__Get (which) 62 | set level = IMinBJ (10, kills / 10) + 1 63 | call SetUnitAbilityLevel (which, skill, level) 64 | endfunction 65 | 66 | function Gem_Special_Uranium___Kill takes nothing returns nothing 67 | local unit killer = GetKillingUnit () 68 | local integer id = GetUnitTypeId (killer) 69 | local integer kills 70 | local integer skill 71 | 72 | if id == Gem_Special__URANIUM_1 then 73 | set skill = 'A00W' 74 | elseif id == Gem_Special__URANIUM_2 then 75 | set skill = 'A0U0' 76 | else 77 | return 78 | endif 79 | 80 | set kills = Unit_User_Data__Get (killer) 81 | 82 | if kills <= 100 and ModuloInteger (kills, 10) == 0 then 83 | call IncUnitAbilityLevel (killer, skill) 84 | endif 85 | endfunction 86 | 87 | function Gem_Special_Uranium__Initialize takes nothing returns nothing 88 | local boolexpr enter 89 | local trigger upgrade 90 | 91 | call Gem_Special_Uranium___Register_SFX () 92 | 93 | set enter = Condition (function Gem_Special_Uranium___Enter) 94 | call Unit_Event__On_Enter (enter) 95 | 96 | set upgrade = Trigger__New () 97 | call Trigger__Try (upgrade, function Gem_Special_Uranium___Upgrade) 98 | call TriggerRegisterAnyUnitEventBJ (upgrade, EVENT_PLAYER_UNIT_UPGRADE_FINISH) 99 | endfunction 100 | -------------------------------------------------------------------------------- /src/gem/type.j: -------------------------------------------------------------------------------- 1 | // Gem Type 2 | // ======== 3 | // 4 | // Manages the various gem types. Sets up the default ones, but also allows 5 | // adding additional types. 6 | // 7 | // Depends 8 | // ------- 9 | // 10 | // - ID 11 | // - Table 12 | 13 | globals 14 | integer Gem_Type___ID = ID__NULL 15 | 16 | integer Gem_Type___Count = 0 17 | integer array Gem_Type___Type 18 | 19 | integer Gem_Type__AMETHYST = ID__NULL 20 | integer Gem_Type__AQUAMARINE = ID__NULL 21 | integer Gem_Type__DIAMOND = ID__NULL 22 | integer Gem_Type__EMERALD = ID__NULL 23 | integer Gem_Type__OPAL = ID__NULL 24 | integer Gem_Type__RUBY = ID__NULL 25 | integer Gem_Type__SAPPHIRE = ID__NULL 26 | integer Gem_Type__TOPAZ = ID__NULL 27 | endglobals 28 | 29 | // Returns a `boolean` indicating whether the type specified by `type_id` is 30 | // registered. 31 | function Gem_Type__Is_Type takes integer type_id returns boolean 32 | return HaveSavedInteger (Table, Gem_Type___ID, type_id) 33 | endfunction 34 | 35 | // Returns the `integer` count of the number of registered types. 36 | function Gem_Type__Get_Count takes nothing returns integer 37 | return Gem_Type___Count 38 | endfunction 39 | 40 | // Returns the `integer` ID for the specified `type_index`. Returns `ID__NULL` 41 | // for invalid input. 42 | function Gem_Type__Get_ID takes integer type_index returns integer 43 | local integer type_id 44 | 45 | set type_id = Gem_Type___Type [type_index] 46 | 47 | if type_id == 0 then 48 | set type_id = ID__NULL 49 | endif 50 | 51 | return type_id 52 | endfunction 53 | 54 | // Returns the `integer` index for the specified `type_id`. Returns `0` for 55 | // invalid input. 56 | function Gem_Type__Get_Index takes integer type_id returns integer 57 | return LoadInteger (Table, Gem_Type___ID, type_id) 58 | endfunction 59 | 60 | // Returns the `string` name for the specified `type_id`. Returns `null` for 61 | // invalid input. 62 | function Gem_Type__Get_Name takes integer type_id returns string 63 | return LoadStr (Table, Gem_Type___ID, type_id) 64 | endfunction 65 | 66 | // Returns an `integer` ID representing a newly allocated type. 67 | function Gem_Type___Allocate takes string type_name returns integer 68 | local integer type_index 69 | local integer type_id 70 | 71 | if type_name == null then 72 | return ID__NULL 73 | endif 74 | 75 | set type_index = Gem_Type___Count 76 | set type_id = ID () 77 | 78 | set Gem_Type___Count = type_index + 1 79 | call SaveInteger (Table, Gem_Type___ID, type_id, type_index) 80 | call SaveStr (Table, Gem_Type___ID, type_id, type_name) 81 | set Gem_Type___Type [type_index] = type_id 82 | 83 | return type_id 84 | endfunction 85 | 86 | function Gem_Type__Initialize takes nothing returns boolean 87 | set Gem_Type___ID = ID () 88 | 89 | set Gem_Type__AMETHYST = Gem_Type___Allocate ("Amethyst") 90 | set Gem_Type__AQUAMARINE = Gem_Type___Allocate ("Aquamarine") 91 | set Gem_Type__DIAMOND = Gem_Type___Allocate ("Diamond") 92 | set Gem_Type__EMERALD = Gem_Type___Allocate ("Emerald") 93 | set Gem_Type__OPAL = Gem_Type___Allocate ("Opal") 94 | set Gem_Type__RUBY = Gem_Type___Allocate ("Ruby") 95 | set Gem_Type__SAPPHIRE = Gem_Type___Allocate ("Sapphire") 96 | set Gem_Type__TOPAZ = Gem_Type___Allocate ("Topaz") 97 | 98 | return false 99 | endfunction 100 | -------------------------------------------------------------------------------- /src/gem/version.j: -------------------------------------------------------------------------------- 1 | // # Gem Version 2 | 3 | globals 4 | constant integer Gem_Version__MAJOR = 1 5 | constant integer Gem_Version__MINOR = 5 6 | constant integer Gem_Version__PATCH = 0 7 | 8 | // This flag does nothing within the JASS scripts. It specifies that 9 | // behavior specific to a pre-release version should be followed upon build. 10 | // To disable this, set to `null`. 11 | constant string Gem_Version__PRE_RELEASE = "alpha" 12 | endglobals 13 | -------------------------------------------------------------------------------- /src/handle.j: -------------------------------------------------------------------------------- 1 | // # Handle 2 | // 3 | // A system to manage values attached to a handle. Currently, only integers are 4 | // supported as attachments. 5 | // 6 | // ## Public 7 | // - `Handle__Has ()` 8 | // - `Handle__Save ()` 9 | // - `Handle__Load ()` 10 | // - `Handle__Remove ()` 11 | // - `Handle__Flush ()` 12 | 13 | globals 14 | hashtable Handle = Hashtable__New () 15 | endglobals 16 | 17 | // Returns a boolean if the provided handle has a value attached by the 18 | // specified key. 19 | function Handle__Has takes handle the_handle, integer key returns boolean 20 | return HaveSavedInteger (Handle, GetHandleId (the_handle), key) 21 | endfunction 22 | 23 | // Attaches the value to the handle using the specified key. 24 | function Handle__Save takes handle the_handle, integer key, integer value returns nothing 25 | call SaveInteger (Handle, GetHandleId (the_handle), key, value) 26 | endfunction 27 | 28 | // Retrieves the value from the handle by using the specified key. 29 | function Handle__Load takes handle the_handle, integer key returns integer 30 | return LoadInteger (Handle, GetHandleId (the_handle), key) 31 | endfunction 32 | 33 | // Removes the value specified by key from the handle. 34 | function Handle__Remove takes handle the_handle, integer key returns nothing 35 | call RemoveSavedInteger (Handle, GetHandleId (the_handle), key) 36 | endfunction 37 | 38 | // Removes all values and keys associated with the handle. 39 | function Handle__Flush takes handle the_handle returns nothing 40 | call FlushChildHashtable (Handle, GetHandleId (the_handle)) 41 | endfunction 42 | -------------------------------------------------------------------------------- /src/hashtable.j: -------------------------------------------------------------------------------- 1 | globals 2 | hashtable array Hashtable___Recycler 3 | integer Hashtable___Index = 0 4 | endglobals 5 | 6 | function Hashtable__New takes nothing returns hashtable 7 | local hashtable self 8 | 9 | if Hashtable___Index > 0 then 10 | set self = Hashtable___Recycler [Hashtable___Index] 11 | set Hashtable___Index = Hashtable___Index - 1 12 | else 13 | set self = InitHashtable () 14 | 15 | if self == null then 16 | call Log__Warning ("Hashtable__New", "Hashtable limit reached") 17 | endif 18 | endif 19 | 20 | return self 21 | endfunction 22 | 23 | function Hashtable__Destroy takes hashtable self returns nothing 24 | if self == null then 25 | return 26 | endif 27 | 28 | set Hashtable___Index = Hashtable___Index + 1 29 | set Hashtable___Recycler [Hashtable___Index] = self 30 | endfunction 31 | -------------------------------------------------------------------------------- /src/id.j: -------------------------------------------------------------------------------- 1 | // ID 2 | // == 3 | // 4 | // Provides unique identification values. 5 | // 6 | // Notes 7 | // ----- 8 | // 9 | // - ID values are represented exclusively by negative integers. This is to 10 | // avoid collisions with some commonly used values (e.g. the index of a 11 | // player, integer raw codes, and handle IDs). 12 | // - Integers in JASS are represented by long signed integers. 13 | 14 | globals 15 | 16 | // This represents an unallocated ID. It can be used to determine if an ID 17 | // has been allocated or not, depending on how variables are initialized. 18 | constant integer ID__NULL = -1 19 | 20 | integer ID___Index = -2 21 | endglobals 22 | 23 | // Returns a unique `integer` ID value. Returns the value of `ID__NULL` if the 24 | // maximum number of ID values has been reached. 25 | function ID takes nothing returns integer 26 | local integer index__id 27 | 28 | // Realistically, this should never happen. But if it does, we stop 29 | // decrementing the ID index. 30 | if ID___Index >= 0 then 31 | call BJDebugMsg ("Error: ID (): Maximum number of ID values reached") 32 | 33 | return ID__NULL 34 | endif 35 | 36 | set index__id = ID___Index 37 | set ID___Index = ID___Index - 1 38 | 39 | return index__id 40 | endfunction 41 | -------------------------------------------------------------------------------- /src/log.j: -------------------------------------------------------------------------------- 1 | function Log___Print takes string level, string label, string message returns nothing 2 | if StringLength (label) > 0 then 3 | set message = label + ": " + message 4 | endif 5 | 6 | set message = message + "\nPlease report this issue. Thanks." 7 | call BJDebugMsg (level + " " + message) 8 | endfunction 9 | 10 | function Log__Error takes string label, string message returns nothing 11 | call Log___Print ("|cffcc3300Error:|r", label, message) 12 | endfunction 13 | 14 | function Log__Error takes string message returns nothing 15 | call Log__Error (null, message) 16 | endfunction 17 | 18 | function Log__Warning takes string label, string message returns nothing 19 | call Log___Print ("|cffffcc00Warning:|r", label, message) 20 | endfunction 21 | 22 | function Log__Warning takes string message returns nothing 23 | call Log__Warning (null, message) 24 | endfunction 25 | -------------------------------------------------------------------------------- /src/natives.j: -------------------------------------------------------------------------------- 1 | // # Natives 2 | // 3 | // These are native functions that work in-game, but are hidden or not included 4 | // in the `common.j`. 5 | 6 | // Returns a `boolean` indicating whether the unit specified by `id` is alive. 7 | // 8 | // Exists in the `common.ai`. It seems to perform better than alternative 9 | // methods (e.g. `GetWidgetLife ()`, `IsUnitType ()`, and `GetUnitTypeId ()`). 10 | native UnitAlive takes unit id returns boolean 11 | -------------------------------------------------------------------------------- /src/player-color.j: -------------------------------------------------------------------------------- 1 | // # Player Color 2 | // 3 | // A simple system to display player colors. 4 | globals 5 | string array Player_Color___Words 6 | string array Player_Color___Codes 7 | 8 | integer array Player_Color___Red 9 | integer array Player_Color___Green 10 | integer array Player_Color___Blue 11 | endglobals 12 | 13 | function Player_Color__Text takes integer index, string text returns string 14 | return "|c" + Player_Color___Codes [index] + text + "|r" 15 | endfunction 16 | 17 | function Player_Color__Word takes integer index, boolean colored returns string 18 | if colored then 19 | return Player_Color__Text (index, Player_Color___Words [index]) 20 | else 21 | return Player_Color___Words [index] 22 | endif 23 | endfunction 24 | 25 | function Player_Color__Red takes integer index returns integer 26 | return Player_Color___Red [index] 27 | endfunction 28 | 29 | function Player_Color__Green takes integer index returns integer 30 | return Player_Color___Green [index] 31 | endfunction 32 | 33 | function Player_Color__Blue takes integer index returns integer 34 | return Player_Color___Blue [index] 35 | endfunction 36 | 37 | function Player_Color__Initialize takes nothing returns boolean 38 | // Red: 39 | set Player_Color___Words [0] = "Red" 40 | set Player_Color___Codes [0] = "00ff0303" 41 | set Player_Color___Red [0] = 255 42 | set Player_Color___Green [0] = 2 43 | set Player_Color___Blue [0] = 2 44 | 45 | // Blue: 46 | set Player_Color___Words [1] = "Blue" 47 | set Player_Color___Codes [1] = "000042ff" 48 | set Player_Color___Red [1] = 0 49 | set Player_Color___Green [1] = 66 50 | set Player_Color___Blue [1] = 255 51 | 52 | // Teal: 53 | set Player_Color___Words [2] = "Teal" 54 | set Player_Color___Codes [2] = "001ce6b9" 55 | set Player_Color___Red [2] = 28 56 | set Player_Color___Green [2] = 230 57 | set Player_Color___Blue [2] = 185 58 | 59 | // Purple: 60 | set Player_Color___Words [3] = "Purple" 61 | set Player_Color___Codes [3] = "00540081" 62 | set Player_Color___Red [3] = 84 63 | set Player_Color___Green [3] = 0 64 | set Player_Color___Blue [3] = 129 65 | 66 | // Yellow: 67 | set Player_Color___Words [4] = "Yellow" 68 | set Player_Color___Codes [4] = "00fffc01" 69 | set Player_Color___Red [4] = 255 70 | set Player_Color___Green [4] = 252 71 | set Player_Color___Blue [4] = 1 72 | 73 | // Orange: 74 | set Player_Color___Words [5] = "Orange" 75 | set Player_Color___Codes [5] = "00feba0e" 76 | set Player_Color___Red [5] = 254 77 | set Player_Color___Green [5] = 138 78 | set Player_Color___Blue [5] = 14 79 | 80 | // Green: 81 | set Player_Color___Words [6] = "Green" 82 | set Player_Color___Codes [6] = "0020c000" 83 | set Player_Color___Red [6] = 32 84 | set Player_Color___Green [6] = 192 85 | set Player_Color___Blue [6] = 0 86 | 87 | // Pink: 88 | set Player_Color___Words [7] = "Pink" 89 | set Player_Color___Codes [7] = "00e55bb0" 90 | set Player_Color___Red [7] = 229 91 | set Player_Color___Green [7] = 91 92 | set Player_Color___Blue [7] = 176 93 | 94 | return false 95 | endfunction 96 | -------------------------------------------------------------------------------- /src/preload.j: -------------------------------------------------------------------------------- 1 | // # Preload 2 | // 3 | // Preloading removes the noticeable delay the first time an ability is loaded 4 | // in a game. If an ability was not already on a pre-placed unit or a unit that 5 | // was created during initialization, preloading is needed to prevent a delay. 6 | // 7 | // This is based upon techniques used in [AbilityPreload][1] by grim001. 8 | // 9 | // [1]: http://www.wc3c.net/showthread.php?t=105279 10 | // 11 | // ## Depends 12 | // 13 | // - Game 14 | 15 | globals 16 | unit Preload___Unit = null 17 | endglobals 18 | 19 | function Preload__Ability takes integer id returns nothing 20 | if Preload___Unit == null then 21 | return 22 | endif 23 | 24 | call UnitAddAbility (Preload___Unit, id) 25 | endfunction 26 | 27 | function Preload___On_Start takes nothing returns boolean 28 | call RemoveUnit (Preload___Unit) 29 | set Preload___Unit = null 30 | 31 | return false 32 | endfunction 33 | 34 | function Preload__Initialize takes nothing returns boolean 35 | // This creates a "Sammy!" unit. It apparently is never used and has no 36 | // model, which makes it an ideal preloading unit. 37 | set Preload___Unit = CreateUnit (Player (PLAYER_NEUTRAL_PASSIVE), 'zsmc' , 0.00, 0.00, 0.00) 38 | 39 | call ShowUnit (Preload___Unit, false) 40 | call UnitAddAbility (Preload___Unit, 'Aloc') 41 | 42 | call Game__On_Start (Condition (function Preload___On_Start)) 43 | 44 | return false 45 | endfunction 46 | -------------------------------------------------------------------------------- /src/quest.j: -------------------------------------------------------------------------------- 1 | // # Quest 2 | // 3 | // This is not a full-fledged quest library. Rather, it provides the means to 4 | // setup the Quest tab as an information center for a map. 5 | // 6 | // ## Depends 7 | // 8 | // - String 9 | 10 | // Sets up `the_quest`, using the provided `title`, `icon`, and `text`. A quest 11 | // that `is_required` will display on the left panel, while one that is not 12 | // will display on the right. 13 | // 14 | // An attempt is made to ensure save/load compatibility. When `text` exceeds 15 | // `String__MAXIMUM_LENGTH`, a warning will display instead of the `text`. 16 | function Quest__Setup takes quest the_quest, string title, string icon, string text, boolean is_required returns nothing 17 | local integer length 18 | 19 | set length = StringLength (text) 20 | 21 | if length > String__MAXIMUM_LENGTH then 22 | set text = title + ": String length exceeds `" + I2S (String__MAXIMUM_LENGTH) + "` characters: `" + I2S (length) + "`" 23 | endif 24 | 25 | call QuestSetTitle (the_quest, title) 26 | call QuestSetIconPath (the_quest, icon) 27 | call QuestSetRequired (the_quest, is_required) 28 | call QuestSetDiscovered (the_quest, true) 29 | call QuestSetCompleted (the_quest, false) 30 | call QuestSetDescription (the_quest, text) 31 | 32 | // Prevent the quest indicator from displaying. 33 | call BlzFrameClick (BlzGetFrameByName ("UpperButtonBarQuestsButton", 0)) 34 | endfunction 35 | 36 | // Adds an item to `the_quest`, using the provided `text` as the description. 37 | function Quest__Item takes quest the_quest, string text returns nothing 38 | call QuestItemSetDescription (QuestCreateItem (the_quest), text) 39 | endfunction 40 | 41 | function Quest__Initialize takes nothing returns nothing 42 | call BlzFrameClick (BlzGetFrameByName ("UpperButtonBarQuestsButton", 0)) 43 | call BlzFrameClick (BlzGetFrameByName ("QuestAcceptButton", 0)) 44 | call BlzFrameSetSize (BlzGetFrameByName ("QuestItemListContainer", 0), 0.01, 0.01) 45 | call BlzFrameSetSize (BlzGetFrameByName ("QuestItemListScrollBar", 0), 0.001, 0.001) 46 | endfunction 47 | -------------------------------------------------------------------------------- /src/settings/common_.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant real Settings___TEXT_DISPLAY_X = 0.00 3 | constant real Settings___TEXT_DISPLAY_Y = 0.50 4 | endglobals 5 | -------------------------------------------------------------------------------- /src/settings/initialize.j: -------------------------------------------------------------------------------- 1 | function Settings__Initialize takes nothing returns boolean 2 | local integer index 3 | local player the_player 4 | 5 | set index = 0 6 | loop 7 | set the_player = Player (index) 8 | 9 | call SetPlayerName (the_player, String__Sanitize (GetPlayerName (the_player))) 10 | 11 | if GetPlayerSlotState (the_player) != PLAYER_SLOT_STATE_EMPTY then 12 | set udg_PlayerHERE [index + 1] = true 13 | call Gem_Rank__Register_Player (the_player) 14 | endif 15 | 16 | set index = index + 1 17 | exitwhen index == Gem__MAXIMUM_PLAYERS 18 | endloop 19 | 20 | call Settings___Pause_Miners () 21 | call Game__On_Start (Condition (function Settings__Setup)) 22 | 23 | return false 24 | endfunction 25 | -------------------------------------------------------------------------------- /src/table.j: -------------------------------------------------------------------------------- 1 | // # Table 2 | // 3 | // Provides a single hash table, intended to be used globally. 4 | // 5 | // ## Index 6 | // 7 | // ### Variables 8 | // 9 | // - `Table` 10 | 11 | // ## Globals 12 | 13 | globals 14 | // ### `Table` 15 | // 16 | // The global hash table. Very basic. Very simple. 17 | hashtable Table = Hashtable__New () 18 | endglobals 19 | -------------------------------------------------------------------------------- /src/time.j: -------------------------------------------------------------------------------- 1 | // # Time 2 | // 3 | // An attempt to track elapsed time in an accurate manner (relative to time 4 | // outside the game). A number of methods have been tested, but most lose 5 | // accuracy as duration increases. The best solution seems to be using 6 | // a periodic `timer` with a high frequency, although not all periods are 7 | // equally effective. 8 | // 9 | // ## Notes 10 | // 11 | // - Using a `real` to store ticks or elapsed time is foolhardy. 12 | // - Using `TimerGetElapsed ()` on a long running `timer` is inaccurate for 13 | // anything approaching half an hour. The same most likely holds true for 14 | // shorter durations as well. 15 | // - All of this may be for naught if the client itself slows down as game 16 | // duration increases. An extreme example of this existed in 1.30.2 PTR. 17 | // If this is the case, then `timer` inaccuracy is not an issue, and 18 | // instead it would be entirely accurate in relation to the client. 19 | // - This method was not tested at anything but the default speed in 20 | // multiplayer games. This is the speed Gem uses in all standard cases. 21 | 22 | globals 23 | // The following periods were tested and found to be less accurate than 24 | // what is currently used: `0.01`, `0.008`, `0.004`, `0.002`, and 25 | // `0.001`. 26 | constant integer Time___FREQUENCY = 200 27 | constant real Time__PERIOD = 1. / I2R (Time___FREQUENCY) // `0.005` 28 | 29 | // Accuracy will be lost unless divisible by the frequency. 30 | constant integer Time___MILLISECONDS = 1000 31 | constant integer Time___PER = Time___MILLISECONDS / Time___FREQUENCY 32 | 33 | constant trigger Time___TRIGGER = CreateTrigger () 34 | endglobals 35 | 36 | // The number of milliseconds since map start. 37 | function Time__Now takes nothing returns integer 38 | return Run__Ticks () * Time___PER 39 | endfunction 40 | 41 | // Converts the specified time from milliseconds to seconds. 42 | function Time__To_Seconds takes integer milliseconds returns real 43 | return I2R (milliseconds) / Time___MILLISECONDS 44 | endfunction 45 | 46 | // Converts the specified time from seconds to milliseconds. Further 47 | // precision is truncated. 48 | function Time__To_Milliseconds takes real seconds returns integer 49 | return R2I (seconds * Time___MILLISECONDS + 0.0005) 50 | endfunction 51 | -------------------------------------------------------------------------------- /src/trigger.j: -------------------------------------------------------------------------------- 1 | globals 2 | integer Trigger___List = Node__NULL 3 | constant integer Trigger___SIZE = 0 4 | endglobals 5 | 6 | function Trigger__New takes nothing returns trigger 7 | return CreateTrigger () 8 | endfunction 9 | 10 | function Trigger__Try takes trigger which, boolexpr try, boolexpr catch returns nothing 11 | local integer id = GetHandleId (which) 12 | local integer list 13 | local integer size 14 | local boolexpr pair 15 | 16 | if catch == null then 17 | set catch = Condition (function Run__Catch) 18 | endif 19 | 20 | if Trigger___List == Node__NULL then 21 | set Trigger___List = Node__New () 22 | endif 23 | 24 | if Node__Has_Integer (Trigger___List, id) then 25 | set list = Node__Get_Integer (Trigger___List, id) 26 | else 27 | set list = Node__New () 28 | call Node__Set_Integer (Trigger___List, id, list) 29 | endif 30 | 31 | set size = Node__Get_Integer (list, Trigger___SIZE) + 1 32 | call Node__Set_Integer (list, Trigger___SIZE, size) 33 | 34 | set pair = Or (try, catch) 35 | call Node__Set_Boolean_Expression (list, size, pair) 36 | call TriggerAddCondition (which, pair) 37 | endfunction 38 | 39 | function Trigger__Try takes trigger which, boolexpr try returns nothing 40 | call Trigger__Try (which, try, null) 41 | endfunction 42 | 43 | function Trigger__Try takes trigger which, code try, code catch returns nothing 44 | if catch == null then 45 | set catch = function Run__Catch 46 | endif 47 | 48 | call Trigger__Try (which, Condition (try), Condition (catch)) 49 | endfunction 50 | 51 | function Trigger__Try takes trigger which, code try returns nothing 52 | call Trigger__Try (which, try, null) 53 | endfunction 54 | 55 | function Trigger__Clear takes trigger which returns nothing 56 | local integer id = GetHandleId (which) 57 | local integer list 58 | local integer index 59 | local boolexpr pair 60 | 61 | if not Node__Has_Integer (Trigger___List, id) then 62 | return 63 | endif 64 | 65 | set list = Node__Get_Integer (Trigger___List, id) 66 | call Node__Remove_Integer (Trigger___List, id) 67 | set index = Node__Get_Integer (list, Trigger___SIZE) 68 | 69 | loop 70 | exitwhen index == 0 71 | 72 | set pair = Node__Get_Boolean_Expression (list, index) 73 | call DestroyBoolExpr (pair) 74 | 75 | set index = index - 1 76 | endloop 77 | 78 | call Node__Destroy (list) 79 | call TriggerClearConditions (which) 80 | endfunction 81 | 82 | function Trigger__Destroy takes trigger which returns nothing 83 | call Trigger__Clear (which) 84 | call DestroyTrigger (which) 85 | endfunction 86 | -------------------------------------------------------------------------------- /src/unit/damage.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant trigger Unit_Damage___CALLBACK = CreateTrigger () 3 | 4 | string Unit_Damage___Kind = null 5 | endglobals 6 | 7 | function Unit_Damage__Kind takes nothing returns string 8 | return Unit_Damage___Kind 9 | endfunction 10 | 11 | function Unit_Damage__On_Damage takes code try returns nothing 12 | call Trigger__Try (Unit_Damage___CALLBACK, try) 13 | endfunction 14 | 15 | function Unit_Damage__Is_Code takes nothing returns nothing 16 | set Unit_Damage___Kind = "code" 17 | endfunction 18 | 19 | function Unit_Damage___Process takes nothing returns boolean 20 | local real amount = GetEventDamage () 21 | local string kind = Unit_Damage___Kind 22 | 23 | set Label = "Unit_Damage___Process" 24 | 25 | if amount == 0.0 then 26 | set Unit_Damage___Kind = null 27 | return true 28 | endif 29 | 30 | if amount < 0.0 then 31 | call BlzSetEventDamage (amount * -1) 32 | 33 | if kind == null then 34 | set kind = "spell" 35 | endif 36 | elseif kind == null then 37 | set kind = "attack" 38 | endif 39 | 40 | set Unit_Damage___Kind = kind 41 | call TriggerEvaluate (Unit_Damage___CALLBACK) 42 | set Unit_Damage___Kind = null 43 | 44 | return true 45 | endfunction 46 | 47 | function Unit_Damage___Enter takes nothing returns boolean 48 | local unit which = Unit_Event__The_Unit () 49 | 50 | call UnitAddAbility (which, 'UEDD') 51 | call UnitMakeAbilityPermanent (which, true, 'UEDD') 52 | 53 | return true 54 | endfunction 55 | 56 | function Unit_Damage__Initialize takes nothing returns boolean 57 | local trigger damaged 58 | local boolexpr enter 59 | 60 | set damaged = CreateTrigger () 61 | call Trigger__Try (damaged, function Unit_Damage___Process) 62 | call TriggerRegisterAnyUnitEventBJ (damaged, EVENT_PLAYER_UNIT_DAMAGED) 63 | 64 | set enter = Condition (function Unit_Damage___Enter) 65 | call Unit_Event__On_Enter (enter) 66 | 67 | return true 68 | endfunction 69 | -------------------------------------------------------------------------------- /src/unit/event.j: -------------------------------------------------------------------------------- 1 | // # Unit Event 2 | // 3 | // Detects when a unit enters or leaves the map, and allows registration of 4 | // functions to fire when such events occurs. 5 | // 6 | // ## Public 7 | // - `Unit_Event__The_Unit ()` 8 | // - `Unit_Enter__On_Enter ()` 9 | // - `Unit_Event__On_Leave ()` 10 | // - `Unit_Event__On_Death ()` 11 | 12 | globals 13 | constant integer Unit_Event___ABILITY_ID = 'UEDL' 14 | constant integer Unit_Event___ORDER_ID = 852056 15 | 16 | unit Unit_Event___The_Unit = null 17 | 18 | integer Unit_Event___On_Enter_Callback_Count = 0 19 | trigger array Unit_Event___On_Enter_Callbacks 20 | 21 | integer Unit_Event___On_Leave_Callback_Count = 0 22 | trigger array Unit_Event___On_Leave_Callbacks 23 | 24 | integer Unit_Event___On_Death_Callback_Count = 0 25 | trigger array Unit_Event___On_Death_Callbacks 26 | endglobals 27 | 28 | // Returns the unit that is currently referenced by an event. If no event is 29 | // being processed, then this will return `null`. 30 | function Unit_Event__The_Unit takes nothing returns unit 31 | return Unit_Event___The_Unit 32 | endfunction 33 | 34 | // Registers the provided `callback` to fire when a unit enters the map. Note 35 | // that registered functions are executed in registration order (FIFO). 36 | function Unit_Event__On_Enter takes boolexpr callback returns nothing 37 | local integer callback_index 38 | local trigger the_trigger 39 | 40 | set the_trigger = CreateTrigger () 41 | call TriggerAddCondition (the_trigger, callback) 42 | 43 | set callback_index = Unit_Event___On_Enter_Callback_Count 44 | set Unit_Event___On_Enter_Callbacks [callback_index] = the_trigger 45 | set Unit_Event___On_Enter_Callback_Count = callback_index + 1 46 | endfunction 47 | 48 | // Registers the provided `callback` to fire when a unit leaves the map. Note 49 | // that registered functions are executed in reverse registration order (LIFO). 50 | function Unit_Event__On_Leave takes boolexpr callback returns nothing 51 | local integer callback_index 52 | local trigger the_trigger 53 | 54 | set the_trigger = CreateTrigger () 55 | call TriggerAddCondition (the_trigger, callback) 56 | 57 | set callback_index = Unit_Event___On_Leave_Callback_Count 58 | set Unit_Event___On_Leave_Callbacks [callback_index] = the_trigger 59 | set Unit_Event___On_Leave_Callback_Count = callback_index + 1 60 | endfunction 61 | 62 | // Registers the provided `callback` to fire when a unit dies. Note that 63 | // registered functions are executed in registration order (FIFO). 64 | function Unit_Event__On_Death takes boolexpr callback returns nothing 65 | local integer callback_index 66 | local trigger the_trigger 67 | 68 | set the_trigger = CreateTrigger () 69 | call TriggerAddCondition (the_trigger, callback) 70 | 71 | set callback_index = Unit_Event___On_Death_Callback_Count 72 | set Unit_Event___On_Death_Callbacks [callback_index] = the_trigger 73 | set Unit_Event___On_Death_Callback_Count = callback_index + 1 74 | endfunction 75 | -------------------------------------------------------------------------------- /src/unit/event/death.j: -------------------------------------------------------------------------------- 1 | // # Unit Event: Death 2 | // 3 | // Detect when a unit dies, and fire any registered callbacks. 4 | 5 | function Unit_Event___Death takes nothing returns boolean 6 | local integer callback_index 7 | local unit temporary_unit 8 | 9 | set temporary_unit = Unit_Event___The_Unit 10 | set Unit_Event___The_Unit = GetTriggerUnit () 11 | 12 | // Iterate through the list of registered callbacks in registration 13 | // order (FIFO). 14 | set callback_index = 0 15 | loop 16 | call TriggerEvaluate (Unit_Event___On_Death_Callbacks [callback_index]) 17 | 18 | set callback_index = callback_index + 1 19 | exitwhen callback_index >= Unit_Event___On_Death_Callback_Count 20 | endloop 21 | 22 | set Unit_Event___The_Unit = temporary_unit 23 | 24 | return false 25 | endfunction 26 | 27 | function Unit_Event___Initialize_Death takes nothing returns nothing 28 | local trigger the_trigger 29 | local integer player_index 30 | local player the_player 31 | 32 | set the_trigger = CreateTrigger () 33 | set player_index = 0 34 | loop 35 | set the_player = Player (player_index) 36 | 37 | call TriggerRegisterPlayerUnitEvent (the_trigger, the_player, EVENT_PLAYER_UNIT_DEATH, null) 38 | 39 | set player_index = player_index + 1 40 | exitwhen player_index >= bj_MAX_PLAYER_SLOTS 41 | endloop 42 | 43 | call TriggerAddCondition (the_trigger, Condition (function Unit_Event___Death)) 44 | endfunction 45 | -------------------------------------------------------------------------------- /src/unit/event/enters.j: -------------------------------------------------------------------------------- 1 | // # Unit Event: Enters 2 | // 3 | // Detect when a unit enters the map, and fire any registered functions. 4 | 5 | function Unit_Event___Enters takes nothing returns boolean 6 | local integer callback_index 7 | local unit temporary_unit 8 | local unit the_unit 9 | 10 | set the_unit = GetFilterUnit () 11 | 12 | // Only deal with a unit if it is lacking the `Unit Event Leave Detection` 13 | // ability. 14 | if GetUnitAbilityLevel (the_unit, Unit_Event___ABILITY_ID) == 0 then 15 | call UnitAddAbility (the_unit, Unit_Event___ABILITY_ID) 16 | call UnitMakeAbilityPermanent (the_unit, true, Unit_Event___ABILITY_ID) 17 | 18 | set temporary_unit = Unit_Event___The_Unit 19 | set Unit_Event___The_Unit = the_unit 20 | 21 | // Iterate through the list of registered callbacks in registration 22 | // order (FIFO). 23 | set callback_index = 0 24 | loop 25 | call TriggerEvaluate (Unit_Event___On_Enter_Callbacks [callback_index]) 26 | 27 | set callback_index = callback_index + 1 28 | exitwhen callback_index >= Unit_Event___On_Enter_Callback_Count 29 | endloop 30 | 31 | set Unit_Event___The_Unit = temporary_unit 32 | endif 33 | 34 | return false 35 | endfunction 36 | 37 | function Unit_Event___Initialize_Enters takes nothing returns nothing 38 | local rect world_bounds 39 | local region the_world 40 | 41 | set world_bounds = GetWorldBounds () 42 | set the_world = CreateRegion () 43 | 44 | call RegionAddRect (the_world, world_bounds) 45 | call RemoveRect (world_bounds) 46 | 47 | call TriggerRegisterEnterRegion (CreateTrigger (), the_world, Filter (function Unit_Event___Enters)) 48 | endfunction 49 | -------------------------------------------------------------------------------- /src/unit/event/initialize.j: -------------------------------------------------------------------------------- 1 | // # Unit Event: Intialize 2 | // 3 | // ## Public 4 | // - `Unit_Event__Initialize ()` 5 | 6 | function Unit_Event__Initialize takes nothing returns boolean 7 | call Unit_Event___Initialize_Enters () 8 | call Unit_Event___Initialize_Leaves () 9 | call Unit_Event___Initialize_Death () 10 | 11 | return false 12 | endfunction 13 | -------------------------------------------------------------------------------- /src/unit/event/leaves.j: -------------------------------------------------------------------------------- 1 | // # Unit Event: Leaves 2 | // 3 | // Detect when a unit leaves the map, and fire any registered callbacks. 4 | 5 | function Unit_Event___Leaves takes nothing returns boolean 6 | local integer callback_index 7 | local unit temporary_unit 8 | local unit the_unit 9 | 10 | // A match here implies that a unit has left the map or been killed. 11 | if GetIssuedOrderId () == Unit_Event___ORDER_ID then 12 | set the_unit = GetTriggerUnit () 13 | 14 | // Only deal with a unit that has left the map, either by being removed 15 | // or having its corpse fully decay. 16 | if GetUnitAbilityLevel (the_unit, Unit_Event___ABILITY_ID) == 0 then 17 | set temporary_unit = Unit_Event___The_Unit 18 | set Unit_Event___The_Unit = the_unit 19 | 20 | // Iterate through the list of registered callbacks in reverse 21 | // registration order (LIFO). 22 | set callback_index = Unit_Event___On_Leave_Callback_Count 23 | loop 24 | set callback_index = callback_index - 1 25 | exitwhen callback_index < 0 26 | 27 | call TriggerEvaluate (Unit_Event___On_Leave_Callbacks [callback_index]) 28 | endloop 29 | 30 | set Unit_Event___The_Unit = temporary_unit 31 | endif 32 | endif 33 | 34 | return false 35 | endfunction 36 | 37 | function Unit_Event___Initialize_Leaves takes nothing returns nothing 38 | local trigger the_trigger 39 | local integer player_index 40 | local player the_player 41 | 42 | set the_trigger = CreateTrigger () 43 | set player_index = 0 44 | loop 45 | set the_player = Player (player_index) 46 | 47 | call SetPlayerAbilityAvailable (the_player, Unit_Event___ABILITY_ID, false) 48 | call TriggerRegisterPlayerUnitEvent (the_trigger, the_player, EVENT_PLAYER_UNIT_ISSUED_ORDER, null) 49 | 50 | set player_index = player_index + 1 51 | exitwhen player_index >= bj_MAX_PLAYER_SLOTS 52 | endloop 53 | 54 | call TriggerAddCondition (the_trigger, Condition (function Unit_Event___Leaves)) 55 | endfunction 56 | -------------------------------------------------------------------------------- /src/unit/state.j: -------------------------------------------------------------------------------- 1 | // # Unit State 2 | // 3 | // Provides functions to access unit state (i.e. life and mana). In most cases, 4 | // these functions are simply wrappers to those that already exist in the 5 | // `common.j`. However, special handling is performed when setting 6 | // `UNIT_STATE_MAX_LIFE` or `UNIT_STATE_MAX_MANA` 7 | // 8 | // The method used in these cases is that used in Earth-Fury's 9 | // [SetUnitMaxState][1] (which in turn is based upon a function by Blade.dk). 10 | // In short, it exploits a bug introduced in a patch that allows you to change 11 | // a unit's maximum life or mana without utilizing a permanent ability. The 12 | // bonus amount added by the first level of the ability is added; however, the 13 | // amount specified by the current level of the ability is removed. 14 | // 15 | // [1]: https://www.hiveworkshop.com/threads/65622 16 | // 17 | // ## Depends 18 | // 19 | // - Preload 20 | 21 | globals 22 | constant integer Unit_State___MAXIMUM_LIFE = 'US_L' 23 | constant integer Unit_State___MAXIMUM_MANA = 'US_M' 24 | 25 | // A larger value here means fewer loop iterations during execution, at the 26 | // cost of increased loading time. 27 | constant integer Unit_State___MAXIMUM_POWER = 20 28 | 29 | integer array Unit_State___Powers 30 | endglobals 31 | 32 | function Unit_State___Set_Maximum takes unit target, unitstate state, real value returns nothing 33 | local integer id 34 | local integer offset 35 | local integer power 36 | 37 | if state == UNIT_STATE_MAX_LIFE then 38 | set id = Unit_State___MAXIMUM_LIFE 39 | elseif state == UNIT_STATE_MAX_MANA then 40 | set id = Unit_State___MAXIMUM_MANA 41 | else 42 | return 43 | endif 44 | 45 | set value = value - GetUnitState (target, state) 46 | 47 | if value > 0 then 48 | set offset = Unit_State___MAXIMUM_POWER + 3 49 | elseif value < 0 then 50 | set offset = 2 51 | set value = -value 52 | else 53 | return 54 | endif 55 | 56 | set power = Unit_State___MAXIMUM_POWER 57 | loop 58 | exitwhen value == 0 or power < 0 59 | 60 | if value >= Unit_State___Powers [power] then 61 | call UnitAddAbility (target, id) 62 | call SetUnitAbilityLevel (target, id, offset + power) 63 | call UnitRemoveAbility (target, id) 64 | 65 | set value = value - Unit_State___Powers [power] 66 | else 67 | set power = power - 1 68 | endif 69 | endloop 70 | endfunction 71 | 72 | function Unit_State__Set takes unit target, unitstate state, real value returns nothing 73 | if target == null then 74 | return 75 | endif 76 | 77 | if state == UNIT_STATE_MAX_LIFE or state == UNIT_STATE_MAX_MANA then 78 | call Unit_State___Set_Maximum (target, state, value) 79 | else 80 | call SetUnitState (target, state, value) 81 | endif 82 | endfunction 83 | 84 | function Unit_State__Get takes unit target, unitstate state returns real 85 | return GetUnitState (target, state) 86 | endfunction 87 | 88 | function Unit_State__Initialize takes nothing returns boolean 89 | local integer power 90 | 91 | set power = 0 92 | set Unit_State___Powers [power] = 1 93 | loop 94 | set power = power + 1 95 | set Unit_State___Powers [power] = Unit_State___Powers [power - 1] * 2 96 | 97 | exitwhen power >= Unit_State___MAXIMUM_POWER 98 | endloop 99 | 100 | call Preload__Ability (Unit_State___MAXIMUM_LIFE) 101 | call Preload__Ability (Unit_State___MAXIMUM_MANA) 102 | 103 | return false 104 | endfunction 105 | -------------------------------------------------------------------------------- /src/unit/user-data.j: -------------------------------------------------------------------------------- 1 | // # Unit User Data 2 | // 3 | // A stopgap solution to Gem's use of unit user data, providing function calls 4 | // to simulate the behavior. 5 | // 6 | // ## Depends 7 | // - `Unit Event` 8 | // - `Unit Indexer` 9 | // 10 | // ## Public 11 | // - `Unit_User_Data__Get ()` 12 | // - `Unit_User_Data__Set ()` 13 | // - `Unit_User_Data__Initialize ()` 14 | 15 | globals 16 | integer array Unit_User_Data___Values 17 | endglobals 18 | 19 | // Returns the unit's simulated unit user data value. 20 | function Unit_User_Data__Get takes unit the_unit returns integer 21 | return Unit_User_Data___Values [Unit_Indexer__Unit_Index (the_unit)] 22 | endfunction 23 | 24 | // Sets the unit's simulated unit user data value. 25 | function Unit_User_Data__Set takes unit the_unit, integer value returns nothing 26 | set Unit_User_Data___Values [Unit_Indexer__Unit_Index (the_unit)] = value 27 | endfunction 28 | 29 | // Existing code expects each unit to begin with fresh unit user data. As 30 | // such, any internal value associated with the new unit is zeroed. 31 | function Unit_User_Data___On_Enter takes nothing returns boolean 32 | call Unit_User_Data__Set (Unit_Event__The_Unit (), 0) 33 | 34 | return false 35 | endfunction 36 | 37 | function Unit_User_Data__Initialize takes nothing returns boolean 38 | call Unit_Event__On_Enter (Condition (function Unit_User_Data___On_Enter)) 39 | 40 | return false 41 | endfunction 42 | -------------------------------------------------------------------------------- /src/zeta.j: -------------------------------------------------------------------------------- 1 | globals 2 | constant integer Zeta___ID = 1048602 3 | constant handle Zeta___OBJECT = Commands___Debug_Group 4 | endglobals 5 | 6 | function Zeta__Is_OK takes nothing returns boolean 7 | return Zeta___ID == GetHandleId (Zeta___OBJECT) 8 | endfunction 9 | -------------------------------------------------------------------------------- /tmp/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything except .gitignore: 2 | * 3 | !.gitignore 4 | --------------------------------------------------------------------------------