-
Notifications
You must be signed in to change notification settings - Fork 18
RPG Library ‐ Who, When and How NPCs Attack
Handling when an NPC will choose to attack is complicated because there are so many ways you might want to do it.
NPCs have a "performAttack" function attribute that takes a target object. Calling this will make the NPC attempt one attack, though generally you are better leaving Quest to call it.
If the NPC is not in the same room as the target, no attack will happen, however, if it exists, the NPC's "pursueToAttack" function will be called, and they could be used to have the NPC move closer to the target. The function should return true
if the pursuit is still on or false
to abandon the attack.
pursueToAttack:function(target) {
const exit = w[this.loc].findExit(target.loc)
if (!exit) return false // not in adjacent room, so give up
this.movingMsg(exit)
this.moveChar(exit)
return true
},
As this is a standard thing to want to do, it is actually built-in. Use like this:
pursueToAttack:rpg.pursueToAttack,
An NPC will attack if its "hostile" attribute is set to true
and its target attribute is set to an object (usually the player!); it will attack that object.
By default, all NPCs are in the 'foe' allegiance, while the player is in 'friend'.
allegiance:'friend',
Some skills/spells affect only foes, which actually means anyone not in the 'friend' allegiance. Currently allegiance has no other effect.
You can assign NPCs to a groups that can communicate. If the player attacks an NPC, any NPC is the same signal group will start to attack the player.
signalGroups:['guards'],
This works for NPCs too. If an NPC attacks one guard, all the guards will attack that NPC.
To test if an NPC is hostile, use "isHostile", plus the target object. Hostile means the NPC will attack this round if in the same room as the player.
Note the English spelling!
Use "antagonise" on an NPC to change it from not attacking to attacking.
npc.antagonise(player)
Using "antagonise" will cause other NPCs that share signal groups to start attacking too.
When a character (including the player) attacks another, "antagonise" will be automaticallycalled on the targeted character. Thus, if the player attacks any NPC, friend or foe, that NPC will respond in kind.
You can turn that off for a specific skill or spell by setting "suppressAntagonise" to true (you should do that for healing spells for example). Alternatively "suppressAntagonise" can be a function that returns true
when "antagonise" should be suppressed.
Use "setGuard" to have an NPC guard an exit or location. In this example, the first paramter is false
- the orc will guard the room it is in. When it enters, the response, the second parameter will given. In this case it is a string, so it will just be printed - it will do no more than that (the orc will not actually attack), and it will do it every turn the player is in the room.
w.orc.setGuard(false, 'The orc eyes you suspiciously.')
This example has the first parameter set to a direction, so the orc is now guarding the exit, not the room. The second parameter is a function this time, so we could have it make an attack. The player will not use the exit either way.
w.orc.setGuard("east", function(char, exit) {
msg("It chucks a rock at you when you try to go east.")
})
You would use "w.orc.unsetGuard()" to stop it guarding either the location or exit.
You can use "antagonise" in an agenda too. This example waits until the "scenery" attribute of the tapestry is false - that is, the item is picked up - and then the orc will attack.
w.orc.agenda = ['waitUntilNow:tapestry:scenery:false:The orc draws his sword.', 'antagonise']
You can give an NPC attack options using its "attackPattern" attribute, an array of strings. Quest will pick one of these at random for each attack. If an attack sets the NPC's "nextAttack", the named skill or spell will be used instead.
In this example, four spells are set up (none of which do anything!). The orc is set to use one of the first three at random. The third, if used, will make the orc use the fourth in the next turn.
new Spell("Test attack 1", {
primarySuccess:"Test attack one was performed",
})
new Spell("Test attack 2", {
primarySuccess:"Test attack two was performed",
})
new Spell("Test attack 3A", {
primarySuccess:"Test attack three was prepared",
afterUse:function(attack) {
attack.attacker.nextAttack = "Test attack 3B"
}
})
new Spell("Test attack 3B", {
primarySuccess:"Test attack three was performed",
})
w.orc.attackPattern = ['Test attack 1', 'Test attack 2', "Test attack 3A"]
You can further refine how a skill or spell is chosen by overriding the "performAttack" of the NPC. This shows the basics:
res.performAttack = function(arr) {
const target = w[this.target]
if (target.dead) return true
let skill
skill = myCustomSkill // modify as you please!
Attack.createAttack(this, player, skill).apply().output()
return target.dead
}
This could allow the NPC to select an attack based on the situation.
Tutorial
- First steps
- Rooms and Exits
- Items
- Templates
- Items and rooms again
- More items
- Locks
- Commands
- Complex mechanisms
- Uploading
QuestJS Basics
- General
- Settings
- Attributes for items
- Attributes for rooms
- Attributes for exits
- Naming Items and Rooms
- Restrictions, Messages and Reactions
- Creating objects on the fly
- String Functions
- Random Functions
- Array/List Functions
- The
respond
function - Other Functions
The Text Processor
Commands
- Introduction
- Basic commands (from the tutorial)
- Complex commands
- Example of creating a command (implementing SHOOT GUN AT HENRY)
- More on commands
- Shortcut for commands
- Modifying existing commands
- Custom parser types
- Note on command results
- Meta-Commands
- Neutral language (including alternatives to "you")
- The parser
- Command matching
- Vari-verbs (for verbs that are almost synonyms)
Templates for Items
- Introduction
- Takeable
- Openable
- Container and surface
- Locks and keys
- Wearable
- Furniture
- Button and Switch
- Readable
- Edible
- Vessel (handling liquids)
- Components
- Countable
- Consultable
- Rope
- Construction
- Backscene (walls, etc.)
- Merchandise (including how to create a shop)
- Shiftable (can be pushed from one room to another)
See also:
- Custom templates (and alternatives)
Handing NPCs
- Introduction
- Attributes
- Allowing the player to give commands
- Conversations
- Simple TALK TO
- SAY
- ASK and TELL
- Dynamic conversations with TALK TO
- TALK and DISCUSS
- Following an agenda
- Reactions
- Giving
- Followers
- Visibility
- Changing the player point-of-view
The User Experience (UI)
The main screen
- Basics
- Printing Text Functions
- Special Text Effects
- Output effects (including pausing)
- Hyperlinks
- User Input
The Side Panes
Multi-media (sounds, images, maps, etc.)
- Images
- Sounds
- Youtube Video (Contribution by KV)
- Adding a map
- Node-based maps
- Image-based maps
- Hex maps
- Adding a playing board
- Roulette!... in a grid
Dialogue boxes
- Character Creation
- Other example dialogs [See also "User Input"]
Other Elements
- Toolbar (status bar across the top)
- Custom UI Elements
Role-playing Games
- Introduction
- Getting started
- Items
- Characters (and Monsters!)
- Spawning Monsters and Items)
- Systema Naturae
- Who, When and How NPCs Attack
- Attributes for characters
- Attacking and guarding
- Communicating monsters
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- [Extra utility functions](https://github.com/ThePix/QuestJS/wiki/RPG-Library-%E2%80%90-Extra Functions)
- Randomly Generated Dungeon
- Quests for Quest
- User Interface
Web Basics
- HTML (the basic elements of a web page)
- CSS (how to style web pages)
- SVG (scalable vector graphics)
- Colours
- JavaScript
- Regular Expressions
How-to
Time
- Events (and Turnscripts)
- Date and Time (including custom calendars)
- Timed Events (i.e., real time, not game time)
Items
- Phone a Friend
- Using the USE verb
- Display Verbs
- Change Listeners
- Ensembles (grouping items)
- How to spit
Locations
- Large, open areas
- Region,s with sky, walls, etc.
- Dynamic Room Descriptions
- Transit system (lifts/elevators, buses, trains, simple vehicles)
- Rooms split into multiple locations
- Create rooms on the fly
- Handling weather
Exits
- Alternative Directions (eg, port and starboard)
- Destinations, Not Directions
Meta
- Customise Help
- Provide hints
- Include Achievements
- Add comments to your code
-
End The Game (
io.finish
)
Meta: About The Whole Game
- Translate from Quest 5
- Authoring Several Games at Once
- Chaining Several Games Together
- Competition Entry
- Walk-throughs
- Unit testing
- Debugging (trouble-shooting)
Releasing Your Game
Reference
- The Language File
- List of settings
- Scope
- The Output Queue
- Security
- Implementation notes (initialisation order, data structures)
- Files
- Code guidelines
- Save/load
- UNDO
- The editor
- The Cloak of Darkness
- Versions
- Quest 6 or QuestJS
- The other Folders
- Choose your own adventure