User Tools

Site Tools


ixe:features:custom:apexevolution

Apex Evolution

Made by qople

This page is a work in progress. Todos:
  • Add images
  • Finish “Shot System” section

About

Apex Evolution, or AEV for short, is a game mode based on the likes of Vampire Survivors. You play as a ship you can control and move around, and collect upgrades you can use to add weapons to your ship, or upgrade existing weapons.

Features

  • Randomly selected upgrades, different every run
  • Several ships to choose from, each offering a different experience
  • Special artifacts to power up your ship and weapons
  • Optional endless survival mode on clearing all creeper from the level

How to Play

Starting

When loading into a level, you can select a ship from the inventory menu, and place it where you want to start. As soon as you place your ship, your selection will be locked in.

Moving

After placing your ship, you are free to unpause. You can move your ship around with your default map movement keys, and dig and paint shields as normal. If you press the Custom1 hotkey, which defaults to keypad1 but can be rebound in controls settings, your ship will break into pixels and move to the position of your mouse.

Experience

As you destroy creeper, you gain experience and fill up the bar at the top of the screen. When it fills up all the way, you can choose an upgrade to give yourself. If preferred, the number keys 1 to 3 can be used to select an upgrade instead of clicking it.

Nullifying Enemies

If you get and stay close to an enemy, you will nullify it. Nullifying any enemy gives you a special upgrade choice.

Making Your Own AEV Level

This section only applies if you want to make your own AEV level. You do not need any knowledge of coding, but it is assumed you have basic knowledge of how to make a normal IXE map.

Import the Mod

Adding AEV to your editor project is as simple as getting the ApexEvolution folder from a level in colonies, or taking the most recent version of the folder from this GitHub repository, then putting the whole folder into your editor project's base folder (“ApexEvolution” should be in the same folder as “save.irpl”).

The folders for all editor projects can be found here:

%userprofile%\AppData\Roaming\CreeperWorldIXE\gamedata\mapeditor

After adding the folder, open the level in the editor, then open the editor menu. Go to the IRPL tab and press the “Build Modules” button (on the top left of the tab). Congratulations! AEV is now in your level. Save and load to make the UI show up, and you're ready to start making your level!

Adding Ships

Now that AEV is in your level, the first thing you should do is add at least one ship to the inventory. This is done the same way as with normal ships: simply add *ONE* of every kind of ship you want to have the option of playing as to the inventory from the editor menu. Note that only AEV ships will work with the mod.

It is recommended that you put every ship you can into the inventory, to increase the replay value of your map.

Limitations of the Mod

At this point, you are free to build whatever level you want! There are some IXE features that are currently unsupported in AEV though, so keep this in mind:

  • Digitalis is currently unsupported. Weapons will not target or damage it.
  • Particles should not be used directly in AEV levels.

Mapmaking Tips

You don't have to listen to anything in this section, but here are some tips for AEV levels:

  • Put chambers close enough together that they can be seen from one another with default zoom levels. If they are farther, put a visual indicator of where the next chamber is. This applies especially if using fog of war.
  • It is recommended to go to creeper maker settings and double its strength, then halve the strength of all sand-based emitters. This leaves more room for the time-based emitter scaling to increase their production later on without emitters filling their entire chambers with creeper maker.
  • Test what chambers are possible to start in, and consider leaving some alternate options to speedrun your level for skilled players.
  • Ensure your level is possible with all ships you have included. If a ship can't clear your level, change the level rather than disabling the ship.

Modifying AEV

Much of this section assumes you have knowledge of IRPL and JSON. Templates are given when possible to ease the process.
AEV is still in active development, and some parts of this process may be changed in future updates. Any changes will be summarized in the mod's changelog. This page is accurate as of version 1.0.

As much as is possible, AEV was designed to be easy to modify and expand, especially with regards to adding new ships, weapons, and upgrades.

Making Ships

Before you add an AEV ship, you should read through this page, which talks about what makes up a custom ship and how to add one in. This section will focus on the process of making an existing ship work with AEV, without rehashing the process of making it too much.

JSON Differences

Rather than use the JSON template on the page above, AEV ships should use this JSON template instead:

Click to display ⇲

Click to hide ⇱

{
	"type": "unit",
	"enemy": false,
	"displayname":"YOURSHIP",
	"image": "YOURSHIP.png",
	"sortingorder": 0,
	"position": [0, 0],
	"pivot": [0.5, 0.5],
	"hasphysics": true,
	"gravityscale": 0,
	"destroysonhealth": false,
	"fowrange": 150,
	"creeperdamages": true,
	"digitalissource": false,
	"nullifiable": false,
	"playercandestroy": false,
	"playercontrolbuildsupply": false,
	"playercontrolammosupply": false,
	"isapex": true,
	"isbuilt": true,
	"powerdispatchstoremax": 50,
	"powergeneration": [200, 200, 0],
	"maxammo": 50,
	"controllers": 	[
						{
							"name": "ondestroy_sandexplosion",
							"amt": 256,
							"minvelocity": 1.5,
							"maxvelocity": 3,
							"color0":[0.2, 0.4, 2],
							"color1":[0.2, 0.6, 2],
							"sandtype": 2
						}
					],
	"scripts": [
		{"name": "/ApexEvolution/Ships/ship.irpl"},
		{"name": "/ApexEvolution/Ships/mobilenullifier.irpl"},
		{"name": "YOURSHIP.irpl"}
		],
	"parts":
		[

		]
}

There are some things you'll have to change:

  • DisplayName should be changed to match your ship's name
  • Image should be renamed to the location of your ship's image in the project structure.
  • In the scripts section, “YOURSHIP.irpl” should be renamed to point to a ship info script made from the template below.
  • Parts should be added for every module you want on the ship. They should follow this naming scheme:
    • “[module][number]”
    • Module is the name of the module, and should match the name in that module's upgrades.irpl file.
    • Number is the order it is unlocked in. The first module should be module0, and so on.
    • For example, the first cannon should be named “cannon0”
  • Parts should use the AEV module paths found in /ApexEvolution/Modules, NOT the vanilla modules!

Ship Info Scripts

Every AEV ship must have a ship info script for the mod to work. For many ships you may not have to write your own code at all, just copy the template and write in the information specific to your ship. The template is as follows:

Click to display ⇲

Click to hide ⇱

# This is a template that can be used to make your own ship work in Apex Evolution!
# I have attempted to make this as easy as possible, and explain things where I can.

# IMPORTANT:
# If the module you want to add (e.g. rocket) can be found in the "modules" folder in this mod,
# USE THAT PART PATH INSTEAD OF THE VANILLA ONE OR IT WILL NOT WORK!!!!!!!!!!

# Module count is determined automatically, but their lookup names should be setup properly.
# Each module should be named "module0", "module1", and so on, with no skipped numbers.
# the "module" should be replaced with the name of the module used by the mod.
# The official name of a module can be found in its "upgrades.irpl" file.

$ship_name:"Put the name of your ship here"
$ship_description:"This is the description, keep it informative but short enough to fit in the box"

# -------------------------

# Describe any custom ship modules your ship has on it. This is any module that does not have an upgrades.irpl file associated with it.
# This is a comma separated list. Whitespace is removed, and it is converted to lowercase.
# "Bertha,T H O R ,           spirit" becomes a list of ["bertha", "thor", "spirit"].
# The names of variables below should match this.

$custom_modules:""

# -------------------------

# Describe which modules are enabled by default.
# Variable name should be "start_unlocked_[modulename]".
# The first N modules of the matching name will be made active on game start, the rest will not.
# For instance, if "start_unlocked_cannon" is 2, modules "cannon0" and "cannon1" will start enabled.
# Any other cannon modules defined above will start inactive and can be picked up by upgrades at game time.
# If a variable is not defined, it is assumed to be 0.

$start_unlocked_lathe:1

# ---------------------------

# Define upgrade setup modes for modules.
# Variable name should be "setup_mode_[modulename]"
# Built-in modules will automatically add their modules to the upgrade pool when on the ship if applicable. This is setup mode 0, and only works on built-in modules.
# Custom modules by default have to have their upgrades manually defined below. This is setup mode 1.

# ---------------------------

# Define the primary script or controller for each custom module.
# Variable name should be "primary_behavior_[modulename]"
# If using a controller, give the controller name. 
# If using an IRPL script, the full script path should be given, INCLUDING THE .IRPL AT THE END
# If none is given, it defaults to IRPL script 1.

# ===============================

# Define a list of upgrades associated with this ship. These will be added to the pool only if the ship is picked for the level.
:DefineUpgrades
    CreateList >_upgrades

:Awake
    # This must be in Awake for the description to show up properly.
    RegisterScript("ship")

:Once
    # Defines the "_upgrades" variable containing all this ship's upgrades
    @DefineUpgrades

    Self >mainShip #So the loader script knows who we are
    @LoadShip

# Detects how many modules of the given type are attached to this ship
:DetectModuleNum
    >moduleName
    999 0 do
        if(Self <moduleName i concat GetChild -1 eq)
            i return
        endif
    loop
    999 return


# Sends a message telling the ship loader to initialize the ship and its upgrades, and scrape this script for information about it.
# THIS MUST BE CALLED FOR THIS TO WORK PROPERLY! 
:LoadShip
    SendMsg("LoadShip" 0)

All that is required to set in this template is the ship name and description, and the starting modules. It is recommended to define a ship-specific artifact in :DefineUpgrades, but not necessary. If desired, script variables can be changed in the :Once function, messages can be registered for, and so on.

Making Modules

This section requires moderate to advanced familiarity with IRPL.

“Modules” in AEV are any part that is attached to a ship, that can be affected or unlocked by an upgrade. Any ship part can be turned into an AEV-compatible module, by giving it these two characteristics:

Compatible Module Structure

In order for a module to be properly affected by upgrades, every module variable that can be changed by an upgrade must be present on the module itself and update its effect when the value is changed. For instance, a module whose “damage” variable is stored on its bullet will not be affected by any damage upgrades. Instead, the parent script must set the value on the bullet when it is created, that way the AEV scripts can change the value on the parent and its effect will be seen.

Another common example is fire range. The range indicator circle, and any LOS/RA scan range on the part, must be changed by using setter APIs, not just changing a variable. Because of this, for fire range to properly change these must be explicitly called when the range variable changes.

The upgrades.irpl File

A module's upgrades.irpl script is a global script that must run with “execute_post” as true, and “run_when_paused” as true. It registers the module type under a name that will be used as its reference in upgrades and part names, gives the script or controller name upgrades should effect, and defines the upgrades that are attached to that module.

The template is as follows:

Click to display ⇲

Click to hide ⇱

# Template for adding a module, along with default upgrades

# The name of the module (all lowercase)
$module:"yourmodule"

# Primary behavior of the module
# This is the script or controller whose variables are changed by upgrades.
# Defaults to IRPL script 1 if empty
# If the name does not end in ".irpl" and is not blank, it is interpreted as a controller name instead.
$behavior:""

#Defines all the default upgrades for each included module. 
:AddUpgrades
    # Data is how many of this module are on the main ship to start
    <_DATA >startingModules
    CreateList >upgrades
    
    # An example upgrade. Replace this with your own.
    Table(
        "id"            "example"
        "title"         "Weapon: Your Module"
        "description"   "A module that does something really neat."
        "effect"        "addmodule/yourmodule/1"
        "rarity"        0
        "pickuplimit"   @DetectModuleNum <-startingModules sub 0 max
    ) <upgrades swap AppendToList

    SendMsg("AddUpgradesToPool" <upgrades) 

:Once
    -1 ->*allModules{<module}
    <behavior ->*moduleBehaviors{<module}
    RegisterForMsg("add" <module concat "AddUpgrades")

:DetectModuleNum
    999 0 do
        if(<-*mainShip <module i concat GetChild -1 eq)
            i return
        endif
    loop
    999 return

All that is required is to define the name and behavior for the module. Almost all modules will have at least one upgrade defined to unlock it, and almost all of those will have additional upgrades defined for stat upgrades. More information can be found on how to define upgrades in the upgrade section below.

Upgrades

The upgrade system in AEV is one of the more in-depth systems in the mod, allowing for a lot of freedom and complexity in unlocks and effects.

Overview

There are two ways to define upgrades in AEV: individual upgrades can be defined directly, or special “upgrade templates” can be used, that have less functionality and control, but one upgrade template is interpreted into a group of related upgrades, greatly reducing the time and effort needed to define basic stat upgrades. Both are defined as IRPL tables, and both can be used anywhere upgrades can be defined.

Direct Upgrade Declaration

Directly declaring an upgrade creates a single upgrade with the exact attributes given. It's worth noting that one upgrade in AEV consists of one possible choice in one rarity. Two upgrades that appear to be the same, but with different rarities (for instance, a common “+10% damage” and an uncommon “+15% damage”) are considered separate upgrades and must be initialized separately. In most cases like this though, upgrade templates can be used to define all upgrades at once.

Each upgrade is an IRPL table with the following parameters (case sensitive):

Attribute Required? Description
id yes Defines the internal ID of the upgrade. Used to keep track of pickup limit, or by effects like banupgrade to reference the upgrade. If several upgrades share an ID, they will not show up in the same upgrade choice, will both be banned if either is banned, and share pickup limits. Upgrades can only share IDs if they are in different rarities. If two upgrades with the same rarity and ID are defined, the second upgrade will not be added.
title yes The text that shows at the top of the upgrade choice box
description yes The text that shows at the bottom of the upgrade choice box
effect yes A formatted string that determines what happens when the upgrade is chosen. Format guide below.
rarity yes An integer from 0 to 6 determining rarity. 0 is common, 1 is uncommon, 2 is rare, 3 is epic, 4 is legendary, 5 is artifact, 6 is weapon artifact.
pickuplimit yes The maximum number of times this upgrade can be collected. -1 means no limit.
module no If defined, this upgrade will be attached to the named module. It will not be available to choose until the module is on the ship, and will be removed again from the pool if the module is banned using banmodule. This should be set on all module stat upgrades, but NOT module unlocks, since those need to be available before the first module is added.
prerequisite no If defined, gives the id and pickup amount of another upgrade to be collected before this upgrade is available to choose. Separated by a / character. For instance, prerequisite of “numcannon/2” hides the upgrade from the pool until at least two upgrades with id of “numcannon” have been collected.

As an example, here is the upgrade declaration for the “Lessons Learned” artifact, which increases experience gain:

Table(
    "id"            "xpmult"
    "title"         "Lessons Learned"
    "description"   "+25% XP gain"
    "effect"        "sendmsg/addxpmult/0.25"
    "rarity"        5
    "pickuplimit"   3
)
<_upgrades swap AppendToList

To initialize the upgrade table, it should be put in a list, usually with other upgrades, and then that list should be sent as data on the “AddUpgradesToPool” message channel. In most places where upgrades are defined, the list is defined and sent in the template already, so all you need to do is make sure to add your upgrades to the list.

Upgrade Effects

The effect field in upgrades has many powerful ways you can use it, from simply sending an IRPL message, to changing the stats on modules, to banning upgrades, and more. The general format is as such:

effecttype/arg1/arg2/...

Where effecttype is one of the effect types in the table below, and the arguments match for that effect type.

All current valid effects are as follows:

Adds a module to the ship. Cannot add modules not defined in the ship JSON.

Arguments are: The name of the module to add, then the number of that module to unlock (usually 1).

For example, “addmodule/cannon/1” unlocks one cannon module on the ship.

Module Group Notation

Most effects that reference modules support a special syntax to apply the effect to several modules at once. This is “group notation”. In addition to naming a specific module, these options can be used:

  • Giving “all” for the module name makes the upgrade use all modules on the ship.
  • Giving “unbanned” for the module name makes the upgrade use all currently unbanned modules on the ship.
  • Giving “not_[module]” makes the upgrade use all modules except the one named (e.g. “not_bertha”)
  • A semicolon-separated list can also be given.

Upgrade Templates

Upgrade templates are a shorthand way to define basic stat upgrades for modules in a much more compact manner. They have less control, but are much easier to manage and update. Each upgrade template gets converted into a series of upgrades with similar effects but different strengths and rarities, so all rarities for fire rate upgrades can be defined with a single table, for instance.

Upgrade templates also define which stats are shown in the stat screen.

Each upgrade template has the following attributes:

The variable name the upgrades apply to.

Most stats use an upgrade template that looks mostly like this:

Table(
    "attribute"         "shot_damage"
    "attribute_name"    "damage"
    "module"            "darkling"
    "title"             "Hotter plasma"
    "effect_type"       "incmult"
    "effect_strengths"  "0.1, 0.15, 0.22, 0.33, 0.5"
) <upgrades swap AppendToList

And fire delay upgrades use a template with these stats:

Table(
    "attribute"         "fire_delay"
    "attribute_name"    "fire delay"
    "module"            "maker"
    "title"             "Efficient Chambering"
    "sequential"        true
    "effect_type"       "incmult"
    "effect_strengths"  "-0.1, -0.1, -0.1, -0.1, -0.1"
    "pickup_limit"      "2,    2,    2,    1,    1"
) <upgrades swap AppendToList

Shot System

AEV contains a robust event-based shot system that can efficiently handle hundreds of shots at a time. In version 1.0 it is hard-coded to only apply to the cannon, rocket, bertha, and sentrygun, but an update is planned soon to let mapmakers register new modules to use this feature.

Overview

Each shot type in AEV consists of:

  • A base shot class, such as “cannon” or “rocket”, that determines the basic behavior of the shot.
  • A module name that stats for the shot are pulled from automatically. The proper variables must be defined on the module for the shot to work properly.
  • A series of behaviors that modify the shot, each made of a name, a trigger, and a function to run when that trigger happens.

Shot Classes

Currently, only two types of shots are supported: cannon and rocket. Each has a set of variables that must be defined on them for the shot, or for most behaviors, to work properly. These values will be automatically updated in the shot system when changed by an upgrade. If an external source changes a stat value used by the shot system, it must be manually updated by calling the message “StatsUpdated” with data being a list of: [module name, stat name, new value].

cannon

A cannon shot has the following base logic, without behaviors:

  • Creates a shot (or several) in the direction the unit creating the shot is facing.
  • Each shot moves in a straight line until it hits a wall or leaves the map, then destroys itself.

This logic can be added onto with behaviors, to do things like “destroy the shot when it hits creeper” or “damage creeper when the shot is destroyed”. More on behaviors below.

The following variables must be defined on a module that creates a cannon shot:

The number of shots created with each call to the “CreateShot” message.

rocket

Rocket shots have the following base logic, with no behaviors:

  • One or more shots are made, targeting deepest creeper in range of the unit creating the shot using the module's RA range.
  • The shot follows a path to the target using GetRaPath.
  • When it reaches the end of the path, the shot destroys itself.

This logic can be added onto with behaviors, to do things like “destroy the shot when it hits creeper” or “damage creeper when the shot is destroyed”. More on behaviors below.

The following variables must be defined on a module that creates a cannon shot:

The number of shots created with each call to the “CreateShot” message.

Behaviors

Shot behaviors are at the core of the AEV shot system. They allow every shot to be modified in complex ways, using declarative syntax without sacrificing on efficiency. Each behavior consists of a reference name used to delete the behavior later, a trigger, and a function and arguments to call when that trigger happens.

The basic syntax of a behavior is as follows:

"name/trigger/function/arg1/arg2/..."

Many behavior functions have arguments, but not all are required. As an example, this is a behavior on the cannon:

"basehit/hitcreeper/destroy"

This is a behavior with a reference name of “basehit,” that activates on the shot hitting creeper, and destroys the shot when activated. (There is a separate behavior for damaging creeper on destroy.)

Reference Name

The reference name of a behavior can be anything, and doesn't even have to be unique. It is only used by the “RemoveBehavior” upgrade effect to remove it if needed, and is mostly used to disable the starting behaviors when weapon artifacts are collected.

Triggers

A trigger is simply an event that can happen over the course of a shot's lifetime. If and when it happens, if there are any behaviors on a shot associated with that trigger, the behaviors' associated functions are called.

The current triggers supported by the shot system are:

Called when the shot is first created.

Functions

A behavior's function is the action that is performed when the trigger happens on its shot. Most can accept arguments that can further customize their effects.

Currently suported behaviors are:

Runs a DamageCreeper function at the shot's current position, using the module's “shot_damage”, “shot_damage_distance”, and “shot_damage_count” vars as the inputs.

Optional arguments are: multiplier to damage, multiplier to distance, and multiplier to count, in order. All default to 1 if not listed.

All these behaviors can be combined and added together to produce many of the effects seen in weapon artifacts like piercing shots on the cannon, the AC trail on the maker, or the delayed detonation on the rocket, just with an AddBehavior effect or two.

Making Your Own Shot Types

To be added in a future update. For now, this only applies to the cannon, sentrygun, rocket, and bertha.

ixe/features/custom/apexevolution.txt · Last modified: 2025/04/10 21:16 by qople