Skip to content

Commit bb4f096

Browse files
authored
Merge pull request #357 from runejs/feature/quest-requirements
quest requirements small expansion
2 parents 6335a09 + e0266c3 commit bb4f096

File tree

5 files changed

+84
-19
lines changed

5 files changed

+84
-19
lines changed

data/config/items/equipment/standard-metals/bronze-weapons.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"equipment_type": "one_handed",
1010
"requirements": {
1111
"quests": {
12-
"goblin_diplomacy": 20
12+
"tyn:goblin_diplomacy": 20
1313
}
1414
},
1515
"offensive_bonuses": {

data/config/items/equipment/standard-metals/rune-armour.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@
254254
"crush": 72,
255255
"magic": -6,
256256
"ranged": 80
257+
},
258+
"requirements": {
259+
"quests" : {
260+
"rs:dragon_slayer": "complete"
261+
}
257262
}
258263
}
259264
}

data/config/items/equipment/standard-metals/rune-god-armour.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@
117117
"crush": 72,
118118
"magic": -6,
119119
"ranged": 80
120+
},
121+
"requirements": {
122+
"quests" : {
123+
"rs:dragon_slayer": "complete"
124+
}
120125
}
121126
}
122127
},
@@ -222,6 +227,11 @@
222227
"crush": 72,
223228
"magic": -6,
224229
"ranged": 80
230+
},
231+
"requirements": {
232+
"quests" : {
233+
"rs:dragon_slayer": "complete"
234+
}
225235
}
226236
}
227237
},
@@ -327,6 +337,11 @@
327337
"crush": 72,
328338
"magic": -6,
329339
"ranged": 80
340+
},
341+
"requirements": {
342+
"quests" : {
343+
"rs:dragon_slayer": "complete"
344+
}
330345
}
331346
}
332347
}

src/engine/world/actor/player/player.ts

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { filestore, serverConfig } from '@server/game';
99
import {
1010
findMusicTrack, findNpc, findSongIdByRegionId, musicRegions, equipmentIndex,
1111
EquipmentSlot, getEquipmentSlot, ItemDetails, findItem, findQuest,
12-
npcIdMap, widgets, NpcDetails, PlayerQuest, QuestKey
12+
npcIdMap, widgets, NpcDetails, PlayerQuest, QuestKey, itemMap
1313
} from '@engine/config';
1414
import { daysSinceLastLogin, colors, hexToRgb, rgbTo16Bit,getVarbitMorphIndex } from '@engine/util';
1515
import { OutboundPacketHandler, Isaac } from '@engine/net';
@@ -460,6 +460,25 @@ export class Player extends Actor {
460460
return playerQuest;
461461
}
462462

463+
/**
464+
* Checks if the player has unlocked the required stage of a quest
465+
* @param questId The ID of the quest to find the player's status on.
466+
* @param minimumStage The minimum quest stage required, defaults to completed
467+
* @return boolean if the player has reached the required stage, if the quest does not exist it defaults to true
468+
*/
469+
public hasQuestRequirement(questId: string, minimumStage: QuestKey = 'complete'): boolean {
470+
if(!questMap[questId]) {
471+
logger.warn(`Quest data not found for ${questId}`);
472+
return true;
473+
}
474+
let playerQuest = this.quests.find(quest => quest.questId === questId);
475+
if(!playerQuest) {
476+
playerQuest = new PlayerQuest(questId);
477+
this.quests.push(playerQuest);
478+
}
479+
return playerQuest.progress === minimumStage || playerQuest.progress >= minimumStage;
480+
}
481+
463482
/**
464483
* Sets a player's quest progress to the specified value.
465484
* @param questId The ID of the quest to set the progress of.
@@ -831,31 +850,36 @@ export class Player extends Actor {
831850
return this.equipment.items[equipmentIndex(equipmentSlot)] || null;
832851
}
833852

834-
public canEquipItem(item: ItemDetails): boolean {
835-
const requirements = item.equipmentData?.requirements;
836-
if (!requirements) return true;
837-
838-
const hasSkillRequirements = Object.entries(requirements.skills || {}).every(([skill, level]) => this.skills.hasLevel(skill as SkillName, level));
839-
const hasQuestRequirements = Object.entries(requirements.quests || {}).every(([quest, stage]) => this.getQuest(quest).progress >= stage);
840853

841-
return hasSkillRequirements && hasQuestRequirements;
842-
}
843-
844-
public missingItemEquipRequirements(item: ItemDetails): string[] {
854+
/**
855+
* Check if a player can equip an item
856+
* @param item either an ItemDetails instance or the string id of the item to be checked
857+
* @return {equipable: boolean, missingRequirements: string[]} equipable is false if for any reason the item can not
858+
* be equipped, if it can not be equipped, a list of reasons are attached as the missingRequirements array
859+
*
860+
* defaults to equipable=true if the item string id does not exist
861+
*/
862+
public canEquipItem(item: ItemDetails | string): { equipable: boolean, missingRequirements?: string[] } {
863+
if(typeof item === 'string') {
864+
item = itemMap[item];
865+
if(!item) {
866+
return { equipable: true }
867+
}
868+
}
845869
const missingRequirements = [];
846870
const requirements = item.equipmentData?.requirements;
847-
if (!requirements) return missingRequirements;
871+
if (!requirements) return { equipable: true };
848872

849873
missingRequirements.push(
850874
...Object.entries(requirements.skills || {})
851875
.filter(([skill, level]) => !this.skills.hasLevel(skill as SkillName, level))
852876
.map(([skill, level]) => `You need to be at least level ${level} ${skill} to equip this item.`),
853877
...Object.entries(requirements.quests || {})
854-
.filter(([quest, stage]) => this.getQuest(quest).progress < stage)
855-
.map(([quest]) => `You must progress further in the ${quest.replace(/_/g, ' ')} quest to equip this item.`)
878+
.filter(([quest, stage]) => this.hasQuestRequirement(quest, stage))
879+
.map(([quest]) => `You must progress further in the ${quest.replace(/^([a-z]+:)/gm, '').replace(/_/g, ' ')} quest to equip this item.`)
856880
);
857881

858-
return missingRequirements;
882+
return { equipable: missingRequirements.length === 0, missingRequirements: missingRequirements };
859883
}
860884

861885
public equipItem(itemId: number, itemSlot: number, slot: EquipmentSlot | number): boolean {
@@ -884,9 +908,11 @@ export class Player extends Actor {
884908
return;
885909
}
886910

887-
const missingRequirements = this.missingItemEquipRequirements(itemDetails);
888-
if (missingRequirements.length) {
889-
missingRequirements.forEach( s => {this.sendMessage(s)});
911+
const equippable = this.canEquipItem(itemDetails);
912+
if (!equippable.equipable) {
913+
if(equippable.missingRequirements) {
914+
equippable.missingRequirements.forEach(async (s) => this.sendMessage(s));
915+
}
890916
return;
891917
}
892918

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { commandActionHandler } from '@engine/action';
2+
import { questMap } from '@engine/plugins';
3+
4+
const action: commandActionHandler = (details) => {
5+
for (const quest of Object.values(questMap)) {
6+
details.player.sendLogMessage(quest.id, details.isConsole);
7+
}
8+
};
9+
10+
export default {
11+
pluginId: 'promises:quest-list-command',
12+
hooks: [
13+
{
14+
type: 'player_command',
15+
commands: [ 'quest-list', 'quests' ],
16+
handler: action
17+
}
18+
]
19+
};

0 commit comments

Comments
 (0)