Files
novafarma/EMERGENCY_SYSTEMS_RECOVERY/NPCPrivacySystem.js
2026-01-16 02:43:46 +01:00

455 lines
13 KiB
JavaScript

/**
* NPC PRIVACY & HOME DECORATION SYSTEM
* Part of: Game Systems Expansion
* Created: January 4, 2026
*
* Features:
* - Hobby-based automatic interior generation
* - Door lock system (heart-based access)
* - NPC home visit mechanics
* - Relationship effects from visits
* - Privacy violations & consequences
*/
class NPCPrivacySystem {
constructor(game) {
this.game = game;
this.player = game.player;
// Privacy settings
this.privacyLevels = {
PUBLIC: 0, // Anyone can enter (living room, kitchen)
FRIENDLY: 3, // 3+ hearts required
PRIVATE: 5, // 5+ hearts required (bedroom)
INTIMATE: 8, // 8+ hearts required (special rooms)
LOCKED: 10 // 10 hearts or marriage required
};
// Visit tracking
this.visitHistory = {};
this.lastVisitTimes = {};
// NPC home decorations (generated based on hobby)
this.npcHomes = {};
}
/**
* Generate NPC home interior based on hobby
*/
generateNPCHome(npcId) {
const npc = this.game.npcs.get(npcId);
if (!npc) return null;
const hobby = npc.hobby;
// Base home structure
const home = {
npcId: npcId,
rooms: {
living_room: {
name: 'Living Room',
privacyLevel: this.privacyLevels.PUBLIC,
objects: this.generateLivingRoomObjects(hobby)
},
kitchen: {
name: 'Kitchen',
privacyLevel: this.privacyLevels.PUBLIC,
objects: this.generateKitchenObjects(hobby)
},
bedroom: {
name: 'Bedroom',
privacyLevel: this.privacyLevels.PRIVATE,
objects: this.generateBedroomObjects(hobby)
},
hobby_room: {
name: this.getHobbyRoomName(hobby),
privacyLevel: this.privacyLevels.FRIENDLY,
objects: this.generateHobbyRoomObjects(hobby)
}
},
visitCount: 0,
lastVisit: null
};
// Store home
this.npcHomes[npcId] = home;
return home;
}
/**
* Generate living room objects
*/
generateLivingRoomObjects(hobby) {
const base = [
'interior_table_small',
'interior_bookshelf',
'interior_gothic_lantern'
];
// Hobby-specific additions
const hobbyAdditions = {
fishing: ['mounted_fish', 'fishing_net'],
farming: ['grain_sack', 'tool_rack'],
cooking: ['recipe_shelf'],
reading: ['bookshelf', 'reading_chair'],
music: ['guitar_stand', 'music_sheets'],
crafting: ['crafting_workshop']
};
return [...base, ...(hobbyAdditions[hobby] || [])];
}
/**
* Generate kitchen objects
*/
generateKitchenObjects(hobby) {
const base = [
'interior_kitchen_stove',
'interior_kitchen_counter'
];
if (hobby === 'cooking') {
base.push(
'interior_kitchen_fridge',
'interior_kitchen_sink',
'interior_recipe_shelf'
);
}
return base;
}
/**
* Generate bedroom objects
*/
generateBedroomObjects(hobby) {
const base = [
'interior_bed_wooden',
'interior_wardrobe',
'interior_chest_locked'
];
// Personal items based on hobby
const hobbyItems = {
zombie_worker: ['brain_jar', 'work_uniform'],
baker: ['flour_workspace', 'dough_tools'],
barber: ['dreadlock_kit', 'styling_tools'],
fisherman: ['tackle_box', 'fish_collection']
};
return [...base, ...(hobbyItems[hobby] || [])];
}
/**
* Generate hobby room objects
*/
generateHobbyRoomObjects(hobby) {
const hobbyRooms = {
fishing: [
'fishing_rod_rack',
'bait_storage',
'fish_tank',
'mounted_trophy_fish'
],
zombie_worker: [
'brain_jar',
'work_bench',
'tool_storage',
'miner_equipment'
],
baker: [
'flour_workspace',
'mixing_bowls',
'bread_storage',
'recipe_collection'
],
alchemy: [
'interior_alchemy_bottle',
'interior_brewing_cauldron',
'interior_chemistry_set',
'interior_potion_shelf'
],
crafting: [
'interior_crafting_workshop',
'interior_tool_rack',
'material_storage',
'blueprint_table'
],
reading: [
'interior_bookshelf',
'reading_chair',
'ancient_manuscripts',
'writing_desk'
]
};
return hobbyRooms[hobby] || ['generic_workspace'];
}
/**
* Get hobby room name
*/
getHobbyRoomName(hobby) {
const names = {
fishing: 'Fishing Den',
zombie_worker: 'Worker\'s Quarters',
baker: 'Baking Workshop',
alchemy: 'Alchemy Lab',
crafting: 'Craft Room',
reading: 'Library',
music: 'Music Studio',
farming: 'Storage Shed'
};
return names[hobby] || 'Hobby Room';
}
/**
* Attempt to enter NPC room
*/
attemptEntry(npcId, roomId) {
const npc = this.game.npcs.get(npcId);
if (!npc) {
return { success: false, message: 'NPC not found!' };
}
// Generate home if doesn't exist
if (!this.npcHomes[npcId]) {
this.generateNPCHome(npcId);
}
const home = this.npcHomes[npcId];
const room = home.rooms[roomId];
if (!room) {
return { success: false, message: 'Room not found!' };
}
// Check privacy level
const playerHearts = this.player.getRelationshipHearts(npcId);
const requiredHearts = room.privacyLevel;
if (playerHearts < requiredHearts) {
// Privacy violation!
return this.handlePrivacyViolation(npcId, roomId, requiredHearts);
}
// Allowed entry
return this.handleSuccessfulEntry(npcId, roomId);
}
/**
* Handle privacy violation
*/
handlePrivacyViolation(npcId, roomId, requiredHearts) {
const npc = this.game.npcs.get(npcId);
// Relationship penalty
const penalty = (requiredHearts - this.player.getRelationshipHearts(npcId)) * 20;
npc.addRelationshipPoints(-penalty);
// NPC reaction
const reactions = [
"Hey! That's private!",
"What are you doing in my room?!",
"Get out! This is MY space!",
"I can't believe you just walked in here...",
"Privacy, please!"
];
const reaction = Phaser.Utils.Array.GetRandom(reactions);
this.game.showDialogue(npc.name, reaction, {
mood: 'angry',
animation: 'shocked'
});
this.game.showMessage(
`${npc.name} is upset! -${penalty} relationship points`
);
// Player gets kicked out
this.game.player.teleportToLocation('outside_' + npcId + '_home');
return {
success: false,
privacyViolation: true,
penalty: penalty,
requiredHearts: requiredHearts,
currentHearts: this.player.getRelationshipHearts(npcId)
};
}
/**
* Handle successful entry
*/
handleSuccessfulEntry(npcId, roomId) {
const npc = this.game.npcs.get(npcId);
const home = this.npcHomes[npcId];
// Track visit
if (!this.visitHistory[npcId]) {
this.visitHistory[npcId] = [];
}
const visit = {
roomId: roomId,
timestamp: this.game.time.currentTime,
timeOfDay: this.game.time.getTimeOfDay()
};
this.visitHistory[npcId].push(visit);
this.lastVisitTimes[npcId] = this.game.time.currentTime;
home.visitCount++;
home.lastVisit = this.game.time.currentTime;
// Relationship effects based on visit
this.applyVisitEffects(npcId, roomId, visit);
// Enter room scene
this.game.scene.start('NPCRoomScene', {
npcId: npcId,
roomId: roomId,
room: home.rooms[roomId]
});
return {
success: true,
room: home.rooms[roomId],
npc: npc
};
}
/**
* Apply relationship effects from visit
*/
applyVisitEffects(npcId, roomId, visit) {
const npc = this.game.npcs.get(npcId);
const timeOfDay = visit.timeOfDay;
// Visit frequency check
const recentVisits = this.visitHistory[npcId].filter(v => {
const hoursSince = (this.game.time.currentTime - v.timestamp) / 3600;
return hoursSince < 24; // Last 24 hours
});
if (recentVisits.length > 3) {
// Visiting TOO much = annoying
npc.addRelationshipPoints(-10);
this.game.showMessage(
`${npc.name} seems a bit annoyed by frequent visits...`
);
return;
}
// Time of day effects
if (timeOfDay === 'night' && roomId === 'bedroom') {
// Visiting bedroom at night = awkward
npc.addRelationshipPoints(-5);
this.game.showDialogue(
npc.name,
"It's quite late... Is everything okay?",
{ mood: 'concerned' }
);
} else if (timeOfDay === 'morning' && roomId === 'kitchen') {
// Morning kitchen visit = breakfast together!
npc.addRelationshipPoints(5);
this.game.showDialogue(
npc.name,
"Good morning! Care to join me for breakfast?",
{ mood: 'happy' }
);
} else if (roomId === 'hobby_room') {
// Showing interest in hobby = bonus points!
npc.addRelationshipPoints(10);
this.game.showDialogue(
npc.name,
"I'm glad you're interested in my hobby!",
{ mood: 'excited' }
);
}
}
/**
* Get visit statistics for NPC
*/
getVisitStats(npcId) {
const visits = this.visitHistory[npcId] || [];
// Count visits per room
const roomCounts = {};
visits.forEach(visit => {
roomCounts[visit.roomId] = (roomCounts[visit.roomId] || 0) + 1;
});
// Average visits per day
const daysSinceFirstVisit = visits.length > 0
? (this.game.time.currentTime - visits[0].timestamp) / 86400
: 0;
const avgVisitsPerDay = daysSinceFirstVisit > 0
? visits.length / daysSinceFirstVisit
: 0;
return {
totalVisits: visits.length,
roomCounts: roomCounts,
avgVisitsPerDay: avgVisitsPerDay,
lastVisit: this.lastVisitTimes[npcId],
favoriteRoom: Object.keys(roomCounts).reduce((a, b) =>
roomCounts[a] > roomCounts[b] ? a : b, null)
};
}
/**
* Check if player can access special room
*/
canAccessSpecialRoom(npcId, roomId) {
const npc = this.game.npcs.get(npcId);
if (!npc) return false;
const home = this.npcHomes[npcId];
if (!home) return false;
const room = home.rooms[roomId];
if (!room) return false;
const playerHearts = this.player.getRelationshipHearts(npcId);
// Special case: marriage allows LOCKED access
if (room.privacyLevel === this.privacyLevels.LOCKED) {
return this.player.spouse === npcId;
}
return playerHearts >= room.privacyLevel;
}
/**
* Get NPC home UI data
*/
getNPCHomeUIData(npcId) {
if (!this.npcHomes[npcId]) {
this.generateNPCHome(npcId);
}
const home = this.npcHomes[npcId];
const npc = this.game.npcs.get(npcId);
return {
npc: npc,
home: home,
accessibleRooms: Object.keys(home.rooms).filter(roomId =>
this.canAccessSpecialRoom(npcId, roomId)
),
lockedRooms: Object.keys(home.rooms).filter(roomId =>
!this.canAccessSpecialRoom(npcId, roomId)
),
visitStats: this.getVisitStats(npcId)
};
}
}