NPC scripting: Difference between revisions

From Wiki G1R-MP G1 Remake Multiplayer
Jump to navigation Jump to search
Document planned 0.1.9 item stats, armor, runes and experimental map-editor seats/lights; not a release
Document armor catalogs and eight armor-upgrade Lua APIs from upcoming 0.1.9; public release unchanged
Line 363: Line 363:
NPC melee includes explicit armor strength and ranged combat uses effective dexterity. Numeric refresh preserves accepted attack/projectile snapshots; it does not reload ammo or restart prepared casts. NPC toughness and NPC jewelry are not implemented by this addition. These are extensions to existing APIs, not new names or a replacement for their earlier contracts. Not included in public 0.1.8.
NPC melee includes explicit armor strength and ranged combat uses effective dexterity. Numeric refresh preserves accepted attack/projectile snapshots; it does not reload ammo or restart prepared casts. NPC toughness and NPC jewelry are not implemented by this addition. These are extensions to existing APIs, not new names or a replacement for their earlier contracts. Not included in public 0.1.8.
<!-- upcoming019:end -->
<!-- upcoming019:end -->
<!-- armor019:start -->
== Armor parts (from 0.1.9) ==
Upcoming; not included in public 0.1.8. [[Armor catalog]] lists the 26 bases; [[Armor upgrade catalog]] lists all 84 pieces. This existing function/guide is not newly introduced in 0.1.9. The new [[Armor upgrades|upgrade system]] adds per-character top/mid/bottom selections, full presets and separate player/NPC setters. A different base clears the old parts; choosing the same base keeps compatible selections. Identity, skin tint and tattoos remain separate. See the guide for requirements, safe replacement and synchronization validation.
<!-- armor019:end -->

Revision as of 21:46, 18 October 2026

NPC scripting

Available from update 0.1.5. Included in the public 0.1.5 release (Protocol 37). See Update 0.1.5 for the complete function/event index.

Ownership, units and defaults

These are server-side resource APIs. Use spawnNpc to create a human NPC. Mutations require its owning resource; never authorize an incoming client event merely because it contains a valid NPC ID. Validate getEventClient, permissions and gameplay conditions in any remote handler. NPC IDs and player IDs are not interchangeable. Invalid typed values/settings normally return false; wrong Lua argument types can raise binding errors and should be avoided.

Positions/ranges use metres, speeds metres per second, yaw/FOV degrees, animation blending seconds, projectile timing milliseconds. IDs remain opaque identifiers.

Defaults: health/maxHealth=100, invulnerable=true, weapon mode=none, combatTarget=0, melee damage=10; mana=0/maxMana=100, arrows=0, bolts=0. Merely spawning, equipping or setting HP does not start combat. No automatic retaliation, faction hostility or resurrection is installed.

Equipment and animation

  • setNpcWeapon selects an item; setNpcWeaponMode draws it. Modes: none, fist, melee, bow, crossbow, magic. getNpcWeaponMode reads the mode. Changing to a different item holsters; repeating the same item does not.
  • startNpcAnim uses Player animation catalog aliases (not raw asset paths); stopNpcAnim stops them. Weapons must be holstered. Drawing cancels scripted animation. Animations suspend routes/goals/waits rather than discarding them; one-shots finish automatically, loops need a stop.
  • setNpcRotation sets yaw once. setNpcLookAt turns the whole NPC toward the player's current position once. Neither implements head-only tracking; movement may later update yaw.
  • getPlayerWeaponMode is a separate player observation API: none/fist/melee/bow/crossbow/magic or false if unavailable. onPlayerWeaponModeChange reports changes after the initial baseline, not inventory slot changes.

Health and optional melee combat

Use setNpcMaxHealth, setNpcHealth, getNpcHealth, getNpcMaxHealth and setNpcInvulnerable. Increasing maximum HP does not heal. HP=0 causes death; positive HP revives without restoring old combat targeting. Invulnerability blocks damage but not authorized script setters.

setNpcAttackDamage sets base melee-only damage. Zero is explicitly non-damaging. setNpcCombatTarget selects a live player for continuous combat; pass false to stop. Draw a supported mode first. No automatic aggression is enabled. npcAttack is for one ranged/magic attempt, not melee.

-- Run in the resource owning the NPC; playerId/x/y/z must be validated.
local npc = spawnNpc("Guard", "milten", x, y, z, 0)
if npc then
    setNpcMaxHealth(npc, 250)
    setNpcHealth(npc, 250)
    setNpcInvulnerable(npc, false)
    setNpcWeapon(npc, "1h_sword_short_02")
    setNpcWeaponMode(npc, "melee")
    setNpcAttackDamage(npc, 10)
    setNpcCombatMovement(npc, {mode="run", chase=true})
    setNpcCombatTarget(npc, playerId)
end
-- Later: setNpcCombatTarget(npc, false)

Combat temporarily suspends script routes/goals; they can resume after stopping. Target loss, death, pause, weapon changes and damage reactions cancel pending preparation. Already released projectiles can still hit. NPC armor protection follows the verified server garment catalog; unknown bonuses are not guessed. Incoming player hits are validated server-side. onNpcDamage, onNpcDeath and onNpcAttack report committed results; do not apply the same damage again in handlers.

Combat movement

setNpcCombatMovement accepts a partial table; unknown fields/types or an invalid combination reject the entire change. getNpcCombatMovement returns {chase, mode, speed}.

Field Values Default
chase boolean; false holds position while permitting in-range attacks true
mode walk or run walk
speed walk: 0.1..2.5 m/s; run: 2.6..8 m/s 1.8

Specifying mode without speed chooses walk=1.8 or run=4.5. Changing chase alone preserves mode/speed. This configuration does not start combat, replace a route speed or replay equipment/aim preparation. Use setNpcPaused for a full pause.

setNpcCombatMovement(npc, {mode="run", speed=4.5, chase=true})
setNpcCombatMovement(npc, {chase=false}) -- hold, but may attack in range
setNpcCombatMovement(npc, {chase=true})  -- resume pursuit

Pursuit still follows server navigation and dynamic capsule checks. Combat targeting is abandoned beyond 50 metres horizontally or 5 metres vertically; this is distinct from projectile attack range and the configurable perception query. A blocked route is not bypassed with a teleport.

Spells and projectiles

Supported spell keys: fire_bolt, fire_ball, fire_ball_milten, ice_bolt, ice_block, ball_lightning, fist_of_wind. Fire Ball, Milten Fire Ball and Ball Lightning support levels 1..3; the others accept level 1. Catalog-only spells such as sleep/heal are not supported by this NPC combat API.

setNpcSpell selects the spell/level; none clears it. It stops targeting and holsters magic. Draw with setNpcWeaponMode(npc,"magic"). getNpcSpell returns the key, not the level. Use setNpcMana, setNpcMaxMana, getNpcMana, getNpcMaxMana, setNpcAmmo and getNpcAmmo for finite resources. Initial mana and ammo must be supplied explicitly.

-- Existing NPC owned by this resource; attacks cause real gameplay damage.
setNpcSpell(npc, "fire_ball", 1)
setNpcMaxMana(npc, 200)
setNpcMana(npc, 200)
setNpcWeaponMode(npc, "magic")
setNpcCombatConfig(npc, {range=3, consumeMana=true})
setNpcCombatMovement(npc, {mode="run", chase=true})
setNpcCombatTarget(npc, playerId)
-- Runs into range, stops to cast; when target leaves range, pursues again.
-- For one attempt instead of continuous combat: npcAttack(npc, playerId)
setNpcCombatTarget(npc, false)
setNpcWeapon(npc, "bow_small_01")
setNpcAmmo(npc, "arrows", 20)
setNpcWeaponMode(npc, "bow")
npcAttack(npc, playerId)
-- Crossbow alternative: crossbow_01, bolts, mode crossbow.

setNpcCombatConfig / getNpcCombatConfig:

Field Allowed values Default
range 1..40 metres; spell range can further constrain it 15
dexterity 0..100000 10
skillTier integer 0 untrained / 1 trained / 2 master 0
aimTimeMs integer 150..30000 600
cooldownMs integer 360..60000; spell cooldown/recovery still apply 1000
consumeAmmo, consumeMana boolean true

Changing resource/config settings can cancel preparation; do not reapply them every frame. Disabling consumption preserves resources after release, but sufficient initial resources are still required. Ranged damage uses dexterity/skill; spell damage uses the existing spell catalog, not setNpcAttackDamage. Server [ranged] enabled and [magic] enabled switches are respected.

Visibility and collision

isNpcSeeingPlayer tests distance, horizontal cone and custom server sight blockers. Defaults: 15 metres / 120 degrees. setNpcLookAt is independent: it only faces once.

This is not complete native-world physics. Server-authoritative NPC projectiles consider actor capsules and enabled custom navigation prisms with blocksSight=true. They stop on the first blocker; area/cone spell effects check per-target occlusion. Terrain/buildings/doors/native meshes without matching server blocker geometry are not automatically covered. A map-editor object's collision=true does not create a server sight blocker.

Create a prism using createAiNavigationBlocker (default blocksSight=true). Use setAiNavigationBlockerBlocksSight to make it navigation-only; use setAiNavigationBlockerEnabled, updateAiNavigationBlocker and destroyAiNavigationBlocker for lifecycle changes. Disabling/destroying is respected without reloading. For a scripted moving door, synchronize its matching blocker rather than treating it as permanently closed. Ownership/normal navigation limits still apply.

Combat status

getNpcCombatState returns {phase, rejectReason, target, mode, mana, maxMana, arrows, bolts}. phase is a controller string: idle, blocked-or-out-of-range, casting, prepare, draw-or-loaded, aim, recovery or rejected. It is not a complete melee animation state machine. rejectReason is a numeric code for the current ranged/magic subsystem.

onNpcProjectileState sends numeric phase/result/rejectReason and a domain string (ranged or magic). The tables below list the exact protocol enum mapping; they are not new Lua global constants.

SpellCastPhase

Value Meaning
0 None
1 Equip
2 CastStart
3 Charging
4 Channeling
5 Release
6 Recovery
7 Cancel
8 Completed

SpellCastResult

Value Meaning
0 Pending
1 Accepted
2 Rejected
3 Completed
4 Cancelled

SpellRejectReason

Value Meaning
0 None
1 ServerDisabled
2 CatalogMismatch
3 InvalidSpell
4 NotImplemented
5 NotGranted
6 CircleTooLow
7 NotEnoughMana
8 Cooldown
9 InvalidPhase
10 DuplicateCast
11 RateLimited
12 InvalidOrigin
13 InvalidAim
14 InvalidTarget
15 OutOfRange
16 StaleSnapshot

RangedPhase

Value Meaning
0 None
1 Equipped
2 Relaxed
3 AimStart
4 Aiming
5 NotchStart
6 Notched
7 DrawStart
8 Drawing
9 DrawHold
10 Release
11 QuickRelease
12 Recovery
13 ReloadStart
14 Reloading
15 Loaded
16 Cancelled
17 Unequipped

RangedActionResult

Value Meaning
0 Pending
1 Accepted
2 Rejected
3 Completed
4 Cancelled

RangedRejectReason

Value Meaning
0 None
1 ServerDisabled
2 InvalidPlayer
3 InvalidSequence
4 InvalidWeapon
5 WeaponNotEquipped
6 WeaponNotInHand
7 InvalidPhase
8 DuplicateShot
9 RateLimited
10 InvalidOrigin
11 InvalidAim
12 InvalidTarget
13 OutOfRange
14 StaleSnapshot
15 NoAmmo
16 NotLoaded
17 ChargeTooShort
18 ReloadIncomplete

Synchronization and cleanup

Current appearance, equipment/drawn state, life state, ongoing action/cast timing and current projectiles are replayed on relevance entry/late join, without replaying historical damage/releases. Each NPC keeps independent state. Stopping the owner resource/destroying the NPC cleans its state and projectile subsystem; death alone does not necessarily remove projectiles already released.

The update also improves NPC melee hit presentation, bow visibility and return to locomotion after ended attacks. Human crouch/sneak replication and remote attack recovery are automatic presentation changes, not new Lua functions. No local inventory manipulation, head-only gaze or full-world collision expansion is promised by these APIs.

NPC appearance since 0.1.5

The following are server-side functions for human NPCs created by spawnNpc. Only the owning resource can change them. They use the existing remote-character appearance pipeline, not a second body mesh or player inventory. Authoritative values are replayed on relevance entry and late join.

Existing setNpcSkin remains a legacy surface preset, not an alias for setNpcIdentity. NPCs that have never called setNpcIdentity keep the old skin behaviour. After an explicit identity is selected, setNpcSkin does not replace that identity. getNpcData adds identity and identityExplicit to distinguish these states. getNpcIdentity returns "default" before the first explicit identity selection; this does not describe any legacy skin fallback.

setNpcArmor changes the independent garment; setNpcWeapon changes the equipped weapon. Neither new cosmetic setters nor their resets change authoritative HP, equipment, patrol or combat configuration. Appearance rebuilding is asynchronous: true confirms acceptance, not that the render has already finished. Tattoos are visible only on exposed body regions supported by the chosen preset; no new geometry, outfit replacement or arbitrary textures are loaded from scripts.

local npc = spawnNpc("Guide", "default", x, y, z, 0)
if npc then
    setNpcIdentity(npc, "milten")
    setNpcArmor(npc, "water_robe")
    setNpcSkinColor(npc, 90, 60, 40)
    setNpcTattoo(npc, "templar1")
    -- Later, independently:
    setNpcIdentity(npc, "default") -- keeps armor, tint and tattoo
    resetNpcSkinColor(npc)
    resetNpcTattoo(npc)
end

State lasts for this NPC's lifetime. For persistence across a server restart, store the keys/RGB in your resource database and reapply after spawning a new NPC. No client event is automatically trusted or exposed by these APIs.


NPC melee skill tiers (since 0.1.7)

The functions themselves remain available since 0.1.5. Only the additions below are new in 0.1.7; they require matching 0.1.7 client/server support.

  • setNpcCombatConfig accepts optional meleeSkillTier: integer 0 (untrained, default), 1 (trained) or 2 (master). getNpcCombatConfig includes this field in its result table.
  • skillTier remains the separate ranged-combat tier. Changing the melee tier does not overwrite ranged settings. Omitted fields keep their existing values; invalid/unknown fields reject the entire change.
  • This selects ordinary melee presentation/timing for the NPC's equipped family, not its weapon or damage. It does not enable combat, select a target or increase strength/damage. Existing resource ownership and combat controls still apply.
  • A strike already admitted keeps its captured animation/impact deadline. A melee-only or unchanged update does not restart unrelated projectile preparation; changing ranged settings still affects that separate configuration.
  • Use matching updated client/server support to see the new tier presentation, including observers and late join. Players continue using the existing setPlayerSkill API; no new setPlayerCombatStyle function was added.
-- npcId is an existing NPC owned by this server resource.
local ok = setNpcCombatConfig(npcId, {meleeSkillTier=2})
if ok then
    local config = getNpcCombatConfig(npcId)
    if config then outputDebugString("NPC melee tier: " .. config.meleeSkillTier) end
end


Item-type armor bonuses (planned for 0.1.9)

Item type stats adds explicit armor bonusHealth/bonusMana/bonusStrength/bonusDexterity contributions for equipped scripted NPCs, plus the armor protection profile. Unconfigured native bonuses do not silently change existing NPC balance. Base stats and bonuses are separate; raising maxima does not heal/refill and lowering maxima clamps current values without reviving dead NPCs.

setNpcMaxHealth/setNpcMaxMana set BASE maxima; getNpcMaxHealth/getNpcMaxMana return EFFECTIVE maxima. setNpcCombatConfig/getNpcCombatConfig dexterity is BASE dexterity. getNpcData adds baseMaxHealth, baseMaxMana, baseDexterity, mana, maxMana, dexterity, armorHealthBonus, armorManaBonus, armorStrengthBonus and armorDexterityBonus.

NPC melee includes explicit armor strength and ranged combat uses effective dexterity. Numeric refresh preserves accepted attack/projectile snapshots; it does not reload ammo or restart prepared casts. NPC toughness and NPC jewelry are not implemented by this addition. These are extensions to existing APIs, not new names or a replacement for their earlier contracts. Not included in public 0.1.8.

Armor parts (from 0.1.9)

Upcoming; not included in public 0.1.8. Armor catalog lists the 26 bases; Armor upgrade catalog lists all 84 pieces. This existing function/guide is not newly introduced in 0.1.9. The new upgrade system adds per-character top/mid/bottom selections, full presets and separate player/NPC setters. A different base clears the old parts; choosing the same base keeps compatible selections. Identity, skin tint and tattoos remain separate. See the guide for requirements, safe replacement and synchronization validation.