Skip to content

Commit

Permalink
Make targetless cooldown based abilities interact with order looping too
Browse files Browse the repository at this point in the history
They retain the same context menu split as for targeted abilties. Order from the context menu to add as loopable order. Order from the quickbar to trigger immediately as an immediate and non repeating cast.

Unfortunately doesn't work with emergency supplies since the ship would seems to clear its orders and attack instead, but does work very nicely with card purchasing abilities, such as on Commerce Stations or level 5 allondium worlds.
  • Loading branch information
Skeletonxf committed Jun 4, 2021
1 parent a928182 commit acabd27
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 18 deletions.
5 changes: 5 additions & 0 deletions TODOLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ This is primarily intended as a developer focused project planning list, rather
- Port interdict movement fixes to mod pack once stress tested in a few multiplayer games
- Stress test teaching of dummy resources to the AI
- Can unhack Ancient AI components and CP once sure fully working (I think it properly tracks dummy resource changes now?)
- Review the AI's limitation on scouts being only 2, and make this more flexible
- Review the War.as's limitation of only attacking border systems, and make this more flexible
- Thanks Illyia
- Expansion AI Component
- Teach AI to track what types of resources it can colonise do level chaining with so it knows when to stop trying to finish a focus it can't
- Act on this info to reproritise level chains
Expand Down Expand Up @@ -62,6 +65,8 @@ This is primarily intended as a developer focused project planning list, rather
- Make AI respond to flare bomb and gravitron condensor attacks
- Investigate issues with Mechanoid AI being able to build gates
- Make the AI's search for things to colonise when it has no systems more robust - Star Children should still be able to recover while they have Motherships but the current code will attempt to recolonise its home system or just give up.
- Investigate stored labor being drained by time based constructions
- Fix native life emerging when making some planets tier 1/2

- Not planned for any time soon
- Colonisation ships similar to Motherships for other races
Expand Down
12 changes: 12 additions & 0 deletions colonisation-expansion/data/abilities/subsystem/Cloak.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Ability: Cloak
Name: #ABL_CLOAK
Description: #ABL_CLOAK_DESC
Icon: PlateArmor * #5188e6a0

Cooldown: 5
Disable Looping: True

ShowShipSizeValue(RESOURCE_ENERGY, 0.5, 0.005, ResourceIcon::2, #PER_SECOND, #42b4bd)
RequireEnergyMaintenance(0.5, 0.005)

IsStatusToggle(Cloaked)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Ability: MultiTractor

Range: 100
Cooldown: 15
Disable Looping: True


IsStatusToggle(GravityWell)
Expand Down
6 changes: 6 additions & 0 deletions colonisation-expansion/scripts/definitions/abilities.as
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ tidy final class AbilityType {
// a flag for indicating an ability is a resource transfer ability
bool isResourceTransfer = false;
const ResourceType@ resource;
// Flag for turning off looping on certain abilities that wouldn't work
// with it
bool disableLooping;
// [[ MODIFY BASE GAME END ]]

array<IAbilityHook@> hooks;
Expand Down Expand Up @@ -585,6 +588,9 @@ void loadAbilities(const string& filename) {
else
file.error("Could not find AI hook "+value);
}
else if (key.equals_nocase("Disable Looping")) {
type.disableLooping = toBool(value);
}
// [[ MODIFY BASE GAME END ]]
else {
string line = file.line;
Expand Down
1 change: 1 addition & 0 deletions colonisation-expansion/scripts/gui/editor/defs.as
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class AbilityFile : FileDef {
// Include the fields added to AbilityType
field("Resource Transfer", AT_Boolean, "False", doc="Indicate that this ability is used to transfer resources.");
field("Resource", AT_PlanetResource, "", doc="Associate a resource with this ability for scripting uses.");
field("Disable Looping", AT_Boolean, "False", doc="Indicate that this ability should not allow order looping. Only applies to abilities with no targets that do have cooldowns, as this subset would otherwise allow the user to loop them on the assumption that each effect ends before the next cooldown (should be set to true for targetless cooldown abilities that are toggles, like Cloaked).");
// [[ MODIFY BASE GAME END ]]
}

Expand Down
17 changes: 9 additions & 8 deletions colonisation-expansion/scripts/gui/overlays/ContextMenu.as
Original file line number Diff line number Diff line change
Expand Up @@ -751,11 +751,11 @@ class TriggerAbility : SingleSelectionOption {
}

void call(Object@ selected) {
//if (asOrder) {
// obj.addAbilityOrder()
//} else {
if (asOrder) {
selected.addAbilityOrder(id, null, shiftKey);
} else {
selected.activateAbility(id);
//}
}
playOptionSound(sound::order_attack);
}
};
Expand Down Expand Up @@ -1529,11 +1529,12 @@ bool openContextMenu(Object& clicked, Object@ selected = null) {
if(selected !is clicked)
continue;

addOption(menu, selected, clicked, option,
TriggerAbility(abl.id), abl.type.icon);
// [[ MODIFY BASE GAME START ]]
//addOption(menu, selected, clicked, "Order " + option,
// TriggerAbility(abl.id, asOrder=true), abl.type.icon);
// let the player make cooldown targetless abilities as an
// order so they can loop them
bool asOrder = abl.type.cooldown > 0 && !abl.type.disableLooping;
addOption(menu, selected, clicked, option,
TriggerAbility(abl.id, asOrder=asOrder), abl.type.icon);
// [[ MODIFY BASE GAME END ]]
}
else if(abl.type.targets[0].type == TT_Object) {
Expand Down
54 changes: 44 additions & 10 deletions colonisation-expansion/scripts/server/orders/AbilityOrder.as
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ tidy class AbilityOrder : Order {
bool casted = false;
// [[ MODIFY BASE GAME START ]]
bool recastIfNotActive = false;
bool hasNoTargets = false;
// [[ MODIFY BASE GAME END ]]

AbilityOrder(int id, vec3d targ, double range) {
Expand All @@ -21,14 +22,24 @@ tidy class AbilityOrder : Order {
AbilityOrder(int id, Object@ targ, double range) {
abilityId = id;
@objTarget = targ;
// [[ MODIFY BASE GAME START ]]
if (targ is null) {
hasNoTargets = true;
}
// [[ MODIFY BASE GAME END ]]
this.range = range;
}

bool get_hasMovement() {
return true;
return !hasNoTargets; // [[ MODIFY BASE GAME ]]
}

vec3d getMoveDestination(const Object& obj) {
// [[ MODIFY BASE GAME START ]]
if (hasNoTargets) {
return obj.position;
}
// [[ MODIFY BASE GAME END ]]
if(objTarget !is null)
return objTarget.position;
return target;
Expand All @@ -44,6 +55,7 @@ tidy class AbilityOrder : Order {
file >> casted;
// [[ MODIFY BASE GAME START ]]
file >> recastIfNotActive;
file >> hasNoTargets;
// [[ MODIFY BASE GAME END ]]
}

Expand All @@ -56,6 +68,7 @@ tidy class AbilityOrder : Order {
file << casted;
// [[ MODIFY BASE GAME START ]]
file << recastIfNotActive;
file << hasNoTargets;
// [[ MODIFY BASE GAME END ]]
}

Expand All @@ -81,19 +94,40 @@ tidy class AbilityOrder : Order {
realRange += obj.radius;

// [[ MODIFY BASE GAME START ]]
if (recastIfNotActive && casted && !obj.isChanneling(abilityId)) {
bool alreadyTargeting = false;
if (objTarget !is null) {
alreadyTargeting = obj.isTargeting(abilityId, objTarget);
} else {
alreadyTargeting = obj.isTargeting(abilityId, target);
}
if (!alreadyTargeting) {
// we need to change the target back
if (recastIfNotActive && casted && !obj.isChanneling(abilityId) && !obj.isAbilityOnCooldown(abilityId)) {
if (hasNoTargets) {
// we are only added to the context menu for targetless abilities that have cooldowns
// so just immediately recast
casted = false;
} else {
bool alreadyTargeting = false;
if (objTarget !is null) {
alreadyTargeting = obj.isTargeting(abilityId, objTarget);
} else {
alreadyTargeting = obj.isTargeting(abilityId, target);
}
if (!alreadyTargeting) {
// we need to change the target back
casted = false;
}
}
recastIfNotActive = false;
}
if (hasNoTargets) {
if (casted) {
if (obj.isChanneling(abilityId)) {
return OS_BLOCKING;
} else {
return OS_COMPLETED;
}
}
if (obj.isAbilityOnCooldown(abilityId)) {
return OS_BLOCKING;
}
obj.activateAbility(abilityId);
casted = true;
return OS_BLOCKING;
}
// [[ MODIFY BASE GAME END ]]

if(objTarget !is null) {
Expand Down

0 comments on commit acabd27

Please sign in to comment.