Skip to content

Commit

Permalink
Unit.detachMissiles
Browse files Browse the repository at this point in the history
  • Loading branch information
rhazarian committed Mar 17, 2024
1 parent 05b0efd commit 59cd31d
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 65 deletions.
1 change: 1 addition & 0 deletions src/engine/internal/mechanics/ability-duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DURATION_NORMAL_ABILITY_FLOAT_LEVEL_FIELD,
} from "../../standard/fields/ability"

/** @internal For use by internal systems only. */
export const getAbilityDuration = (ability: Ability, target?: Unit): number => {
const level = ability.level
return target != undefined && target.hasClassification(UnitClassification.RESISTANT)
Expand Down
80 changes: 80 additions & 0 deletions src/engine/internal/mechanics/cast-ability.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { AbilityType, AbilityTypeId } from "../../object-data/entry/ability-type"
import { DUMMY_ITEM_ID } from "../object-data/dummy-item"
import { INVENTORY_DUMMY_NATIVE_UNIT } from "../misc/dummy-units"
import { checkNotNull } from "../../../utility/preconditions"
import { INVENTORY_ABILITY_TYPE_ID } from "../object-data/dummy-inventory"
import { map, toLuaSet } from "../../../utility/arrays"

const createItem = CreateItem
const getAbilityId = BlzGetAbilityId
const getItemAbility = BlzGetItemAbility
const getUnitAbilityByIndex = BlzGetUnitAbilityByIndex
const itemAddAbility = BlzItemAddAbility
const setItemBooleanField = BlzSetItemBooleanField
const removeItem = RemoveItem
const unitAddAbility = UnitAddAbility
const unitAddItem = UnitAddItem
const unitDropItemSlot = UnitDropItemSlot
const unitInventorySize = UnitInventorySize
const unitRemoveAbility = UnitRemoveAbility
const unitRemoveItemFromSlot = UnitRemoveItemFromSlot

const INVENTORY_ABILITY_TYPE_IDS = postcompile(() => {
return toLuaSet(
AbilityType.getAllIdsByBaseIds(map(["AInv", "Aihn", "Aien", "Aion", "Aiun"], fourCC))
)
})

/** @internal For use by internal systems only. */
export const castAbility = <Args extends any[]>(
nativeUnit: junit,
abilityTypeId: AbilityTypeId,
prepareAbility?: (nativeAbility: jability, ...args: Args) => void,
...args: Args
): boolean => {
const nativeItem = createItem(DUMMY_ITEM_ID, 0, 0)
unitAddItem(INVENTORY_DUMMY_NATIVE_UNIT, nativeItem)
itemAddAbility(nativeItem, abilityTypeId)
const nativeAbility = checkNotNull(getItemAbility(nativeItem, abilityTypeId))
if (prepareAbility != undefined) {
prepareAbility(nativeAbility, ...args)
}
setItemBooleanField(nativeItem, ITEM_BF_ACTIVELY_USED, true)
setItemBooleanField(nativeItem, ITEM_BF_USE_AUTOMATICALLY_WHEN_ACQUIRED, true)
let success: boolean
if (unitAddItem(nativeUnit, nativeItem)) {
success = true
} else {
let latestInventoryAbilityTypeId = 0
const nativeItemBySlot = new LuaMap<number, jitem>()
const inventorySize = unitInventorySize(nativeUnit)
if (inventorySize != 0) {
for (const slot of $range(0, inventorySize - 1)) {
nativeItemBySlot.set(slot, unitRemoveItemFromSlot(nativeUnit, slot))
}
let unitNativeAbility = getUnitAbilityByIndex(nativeUnit, 0)
let i = 1
while (unitNativeAbility != undefined) {
const abilityTypeId = getAbilityId(unitNativeAbility) as AbilityTypeId
if (INVENTORY_ABILITY_TYPE_IDS.has(abilityTypeId)) {
latestInventoryAbilityTypeId = abilityTypeId
}
unitNativeAbility = getUnitAbilityByIndex(nativeUnit, i)
++i
}
unitRemoveAbility(nativeUnit, latestInventoryAbilityTypeId)
}
unitAddAbility(nativeUnit, INVENTORY_ABILITY_TYPE_ID)
success = unitAddItem(nativeUnit, nativeItem)
unitRemoveAbility(nativeUnit, INVENTORY_ABILITY_TYPE_ID)
if (latestInventoryAbilityTypeId != 0) {
unitAddAbility(nativeUnit, latestInventoryAbilityTypeId)
for (const [slot, nativeItem] of nativeItemBySlot) {
unitAddItem(nativeUnit, nativeItem)
unitDropItemSlot(nativeUnit, nativeItem, slot)
}
}
}
removeItem(nativeItem)
return success
}
32 changes: 32 additions & 0 deletions src/engine/internal/unit/detach-missiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Unit } from "../unit"
import { castAbility } from "../mechanics/cast-ability"
import { BlinkAbilityType } from "../../object-data/entry/ability-type/blink"
import { MAXIMUM_INTEGER } from "../../../math"

const getUnitX = GetUnitX
const getUnitY = GetUnitY
const setUnitX = SetUnitX
const setUnitY = SetUnitY

const BLINK_ABILITY_TYPE_ID = compiletime(() => {
const abilityType = BlinkAbilityType.create()
abilityType.minimumRange = 0
abilityType.maximumRange = MAXIMUM_INTEGER
abilityType.manaCost = 0
abilityType.cooldown = 0
return abilityType.id
})

declare module "../unit" {
interface Unit {
detachMissiles(this: Unit): void
}
}
Unit.prototype.detachMissiles = function () {
const nativeUnit = this.handle
const x = getUnitX(nativeUnit)
const y = getUnitY(nativeUnit)
castAbility(nativeUnit, BLINK_ABILITY_TYPE_ID)
setUnitX(nativeUnit, x)
setUnitY(nativeUnit, y)
}
101 changes: 36 additions & 65 deletions src/engine/object-data/entry/buff-type/applicable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { UnitType } from "../unit-type"
import { TupleOf } from "../../../../utility/types"
import { EventListenerPriority } from "../../../../event"
import { PermanentImmolationAbilityType } from "../ability-type/permanent-immolation"
import { castAbility } from "../../../internal/mechanics/cast-ability"

const createItem = CreateItem
const getAbilityId = BlzGetAbilityId
Expand Down Expand Up @@ -359,79 +360,27 @@ export const internalApplyBuff = (
}

if (applicatorType == ApplicatorType.PHYSICAL_POSITIVE) {
let success: boolean
const nativeUnit = unit.handle
const nativeItem = createItem(DUMMY_ITEM_ID, 0, 0)
unitAddItem(INVENTORY_DUMMY_NATIVE_UNIT, nativeItem)
itemAddAbility(nativeItem, applicatorAbilityTypeId)
const applicatorAbility = checkNotNull(getItemAbility(nativeItem, applicatorAbilityTypeId))
if (level == undefined) {
level = 0
setAbilityIntegerField(applicatorAbility, ABILITY_IF_LEVELS, 1)
}
setAbilityRealLevelField(
applicatorAbility,
ABILITY_RLF_DURATION_NORMAL,
level,
duration ?? 0
)
setAbilityRealLevelField(applicatorAbility, ABILITY_RLF_DURATION_HERO, level, duration ?? 0)
if (movementSpeedIncreaseFactor != undefined) {
setAbilityRealLevelField(
applicatorAbility,
ABILITY_RLF_MOVEMENT_SPEED_INCREASE_BSK1,
level,
movementSpeedIncreaseFactor
)
}
setItemBooleanField(nativeItem, ITEM_BF_ACTIVELY_USED, true)
setItemBooleanField(nativeItem, ITEM_BF_USE_AUTOMATICALLY_WHEN_ACQUIRED, true)
if (level > 0) {
const nativePlayer = unit.owner.handle
if (level != undefined && level > 0) {
const upgradeId =
applicatorUpgradeIdByApplicatorAbilityTypeId.get(applicatorAbilityTypeId)
if (upgradeId != undefined) {
setPlayerTechResearched(getOwningPlayer(nativeUnit), upgradeId, level)
}
}
if (!unitAddItem(nativeUnit, nativeItem)) {
let latestInventoryAbilityTypeId = 0
const nativeItemBySlot = new LuaMap<number, jitem>()
const inventorySize = unitInventorySize(nativeUnit)
if (inventorySize != 0) {
for (const slot of $range(0, inventorySize - 1)) {
nativeItemBySlot.set(slot, UnitRemoveItemFromSlot(nativeUnit, slot))
}
let unitNativeAbility = getUnitAbilityByIndex(nativeUnit, 0)
let i = 1
while (unitNativeAbility != undefined) {
const abilityTypeId = getAbilityId(unitNativeAbility) as AbilityTypeId
if (INVENTORY_ABILITY_TYPE_IDS.has(abilityTypeId)) {
latestInventoryAbilityTypeId = abilityTypeId
}
unitNativeAbility = getUnitAbilityByIndex(nativeUnit, i)
++i
}
unitRemoveAbility(nativeUnit, latestInventoryAbilityTypeId)
}
unitAddAbility(nativeUnit, INVENTORY_ABILITY_TYPE_ID)
success = unitAddItem(nativeUnit, nativeItem)
unitRemoveAbility(nativeUnit, INVENTORY_ABILITY_TYPE_ID)
if (latestInventoryAbilityTypeId != 0) {
unitAddAbility(nativeUnit, latestInventoryAbilityTypeId)
for (const [slot, nativeItem] of nativeItemBySlot) {
unitAddItem(nativeUnit, nativeItem)
unitDropItemSlot(nativeUnit, nativeItem, slot)
}
setPlayerTechResearched(nativePlayer, upgradeId, level)
}
} else {
success = true
}
removeItem(nativeItem)
if (level != undefined && level > 1) {
const success = castAbility(
unit.handle,
applicatorAbilityTypeId,
preparePhysicalPositiveApplicatorAbility,
level,
duration ?? 0,
movementSpeedIncreaseFactor
)
if (level != undefined && level > 0) {
const upgradeId =
applicatorUpgradeIdByApplicatorAbilityTypeId.get(applicatorAbilityTypeId)
if (upgradeId != undefined) {
setPlayerTechResearched(getOwningPlayer(nativeUnit), upgradeId, 0)
setPlayerTechResearched(nativePlayer, upgradeId, 0)
}
}
return success
Expand Down Expand Up @@ -470,6 +419,28 @@ export const internalApplyBuff = (
return success
}

const preparePhysicalPositiveApplicatorAbility = (
ability: jability,
level: number | undefined,
duration: number,
movementSpeedIncreaseFactor?: number
): void => {
if (level == undefined) {
setAbilityIntegerField(ability, ABILITY_IF_LEVELS, 1)
level = 1
}
setAbilityRealLevelField(ability, ABILITY_RLF_DURATION_NORMAL, level, duration)
setAbilityRealLevelField(ability, ABILITY_RLF_DURATION_HERO, level, duration)
if (movementSpeedIncreaseFactor != undefined) {
setAbilityRealLevelField(
ability,
ABILITY_RLF_MOVEMENT_SPEED_INCREASE_BSK1,
level,
movementSpeedIncreaseFactor
)
}
}

/** @internal For use by internal systems only. */
export const removeBuff = (unit: junit, applicableBuffTypeId: number): boolean => {
const applicatorAbilityTypeId = applicatorAbilityTypeIdByApplicatorTypeByApplicableBuffTypeId
Expand Down
1 change: 1 addition & 0 deletions src/engine/unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "./internal/unit/missile"
import "./internal/unit-missile-launch"
import "./internal/unit/ghost-counter"
import "./internal/unit/invulnerability-counter"
import "./internal/unit/detach-missiles"

import "./internal/unit/band-aids/ancestral-spirit-cannibalize"

Expand Down

0 comments on commit 59cd31d

Please sign in to comment.