var MATTIE = MATTIE || {};
MATTIE.multiplayer = MATTIE.multiplayer || {};
MATTIE.menus.multiplayer = MATTIE.menus.multiplayer || {};
MATTIE.scenes.multiplayer = MATTIE.scenes.multiplayer || {};
MATTIE.windows.multiplayer = MATTIE.windows.multiplayer || {};
/**
* @class the class that represents all non local players
*/
class PlayerModel {
constructor(name, actorId) {
/** a username */
this.name = name;
/** @description whether this player can be interacted with or not. */
this.canBeInteractedWith = true;
/** the actor id this player should use */
this.actorId = actorId;
/** the id of the peer this player is hosted on */
this.peerId = undefined;
/** @type {MATTIE.multiplayer.Secondary_Player} */
this.$gamePlayer = undefined;
this.$netActors = new MATTIE.multiplayer.NetActors();
/** battle members that only appear in battle */
this.battleOnlyMembers = [];
/** the actor ids of any and all followers, -1 if not present */
this.followerIds = [];
this.map = 0;
this.isSpectating = false;
this.conversationModel = new MATTIE.multiplayer.Conversations();
/** @description an array of all player's ids who currently in combat with this player */
this.pvpCombatArr = [];
/** @description whether this play is part of a marriage */
this.isMarried = false;
/** @description an array of all peerId's this player is married to */
this.marriedTo = [];
/** @description whether marriage has been initalized or not */
this.marriageSetup = false;
/** @description whether this player is the host of a marriage */
this.isMarriageHost = false;
/** @description the peerid of the host of this marriage */
this.marriageHost = null;
/** @description the troopod this peer is currently incombat with */
this.troopInCombatWith = null;
}
setCanInteract(bool) {
this.canBeInteractedWith = bool;
}
/** @description add an id to the pvp arr if it does not already exist */
addIdToPvp(id) {
if (this.pvpCombatArr.indexOf(id) == -1) this.pvpCombatArr.push(id);
}
/** @description remove an id from the pvp arr if it exists */
removeIdFromPvp(id) {
const index = this.pvpCombatArr.indexOf(id);
if (index > 0) this.pvpCombatArr.slice(index);
}
/** @description remove all values from the pvp arr */
clearPvpArr() {
this.pvpCombatArr = [];
}
/**
* @description check if this player is on the map
* @returns {bool} if this player is on the map
*/
isOnMap() {
return this.map === $gameMap.mapId() || this.$gamePlayer.isOnMap();
}
onInteract() {
// called when this player is interacted with by pressing okay.
if (this.canBeInteractedWith && MATTIE.multiplayer.config.canInteract) {
this.conversationModel.talk($gameParty.leader().actorId(), this);
}
}
resurrect() {
this.setSpectate(false);
}
canResurrect() {
return this.isSpectating;
}
setSpectate(bool, doNotEmit = false) {
const netCont = MATTIE.multiplayer.getCurrentNetController();
if (!doNotEmit) netCont.emitSpectateEvent(bool, this.peerId);
if (this.peerId === netCont.peerId) { // self change spectate event
MATTIE.multiplayer.isSpectator = bool;
if (!bool) {
SceneManager.goto(Scene_Map);
if (MATTIE.actorAPI.lastLeader != MATTIE.static.actors.ghost._data.id) {
MATTIE.actorAPI.changePartyLeader(MATTIE.actorAPI.lastLeader);
} else {
MATTIE.actorAPI.changePartyLeader(MATTIE.static.actors.mercenaryId);
}
} else { //
$gameParty.leader().setHp(50);
SceneManager.goto(MATTIE.scenes.multiplayer.Scene_Spectate);
MATTIE.actorAPI.changePartyLeader(MATTIE.static.actors.ghost._data.id);
const members = $gameParty.members();
for (let index = 1; index < members.length; index++) {
const element = members[index];
$gameParty.removeActor(element.actorId());
}
}
}
this.isSpectating = bool;
}
select(activeMember) {
this.members().forEach((member) => {
if (member === activeMember) {
member.select();
} else {
member.deselect();
}
});
}
members() {
return this.battleMembers();
}
displayMembers() {
const arr = [];
arr.push(this.$gamePlayer.actor());
this.followerIds.forEach((followerId) => {
const actor = this.$netActors.baseActor(followerId);
arr.push(actor);
});
return arr;
}
/** @description get the ids of the actors in this party */
memberIds() {
const arr = [];
arr.push(this.actorId);
this.followerIds.forEach((followerId) => {
arr.push(followerId);
});
return arr;
}
addBattleOnlyMember(actor) {
this.battleOnlyMembers.push(actor);
}
removeBattleOnlyMember(id) {
this.battleOnlyMembers.splice(id, 1);
}
clearBattleOnlyMembers() {
this.battleOnlyMembers = [];
}
battleMembers() {
let arr = this.displayMembers();
if (MATTIE.multiplayer.inBattle) {
arr = arr.concat(this.battleOnlyMembers);
}
// while(arr.length < $gameParty.maxBattleMembers()){
// arr.push(new Game_Actor());
// }
return arr;
}
/**
* set the followers on the playermodel and the $gamePlayer
* @param {int[]} ids the actor ids of any and all followers, -1 if not present
*/
getFollowers() {
this.followerIds = [];
for (let index = 1; index < $gameParty.maxBattleMembers(); index++) {
if ($gameParty.battleMembers()[index]) {
const actorId = $gameParty.battleMembers()[index].actorId();
if (actorId) {
if (actorId != this.actorId && actorId != $gameParty.leader().actorId()) {
this.followerIds[index - 1] = actorId;
} else {
this.followerIds[index - 1] = -1;
}
} else {
this.followerIds[index - 1] = -1;
}
}
}
return this.followerIds;
}
followers() {
const displayMembers = this.displayMembers();
const followers = [];
for (let index = 0; index < displayMembers.length; index++) {
/** @type {Game_Actor} */
const actor = displayMembers[index];
if (actor.actorId() != this.actorId) {
followers.push(actor);
}
}
return followers;
}
setFollowers(ids) {
console.log('set followers');
if (this.$gamePlayer) {
const netFollowers = this.$gamePlayer._followers._data;
for (let index = 0; index < ids.length; index++) {
this.followerIds[index] = ids[index];
const follower = netFollowers[index];
if (follower) {
if (this.followerIds[index] >= 0) {
follower.setActor(this.followerIds[index]);
}
}
}
if (ids.length === 0) {
this.$gamePlayer._followers.setup(null);
}
}
}
setMap(map) {
this.map = map;
}
setActorId(id) {
this.actorId = id;
if (this.$gamePlayer && typeof this.$gamePlayer === typeof MATTIE.multiplayer.Secondary_Player) {
this.$gamePlayer.setActor(id);
this.$gamePlayer.refresh();
}
}
initSecondaryGamePlayer() {
this.$gamePlayer = new MATTIE.multiplayer.Secondary_Player(this.$netActors);
this.$gamePlayer.setActor(this.actorId);
this.getFollowers();
this.$gamePlayer.refresh();
}
updateSelfCoreData() {
this.setActorId($gameParty.leader().actorId());
this.getFollowers();
}
getCoreData() {
if (MATTIE.multiplayer.getCurrentNetController()) {
if (MATTIE.multiplayer.getCurrentNetController().peerId === this.peerId) {
this.updateSelfCoreData();
}
}
const obj = {};
obj.name = this.name;
obj.actorId = this.actorId;
obj.peerId = this.peerId;
obj.followerIds = this.followerIds;
obj.isMarriageHost = this.isMarriageHost;
obj.marriageHost = this.marriageHost;
obj.isMarried = this.isMarried;
obj.marriedTo = this.marriedTo;
return obj;
}
setPeerId(peerId) {
this.peerId = peerId;
this.$netActors.setPeerId(peerId);
}
}
/** set the dir4 current control. dir4 is the direction on the arrow keys. */
Game_Player.prototype.moveOneTile = function (dir4) {
this.ctrlDir4 = dir4;
};
/**
* @description a class that represents any player that is not the one the user is actively controlling.
* @extends Game_Player
* @class
*/
MATTIE.multiplayer.Secondary_Player = function () {
this.initialize.apply(this, arguments);
this.actorId = $gameParty._menuActorId;
};
MATTIE.multiplayer.Secondary_Player.prototype = Object.create(Game_Player.prototype);
MATTIE.multiplayer.Secondary_Player.prototype.constructor = MATTIE.multiplayer.Secondary_Player;
MATTIE.multiplayer.Secondary_Player.prototype.initialize = function (netActors) {
this.ctrlDir4 = 0; // start standing still
this.$netActors = netActors;
Game_Player.prototype.initialize.call(this);
MATTIE.fxAPI.addLightObject(() => this, () => this.torchIsLit());
};
/**
* @description check if this player currently has a torch out
* @returns {boolean}
*/
MATTIE.multiplayer.Secondary_Player.prototype.torchIsLit = function () {
return this._torch || false;
};
/**
* @description set whether this player currently has a torch out
* @param {bool} bool whether the player has a torch active or not
* @returns void
*/
MATTIE.multiplayer.Secondary_Player.prototype.setTorch = function (bool) {
this._torch = bool;
};
// override init members to use netfollowers instead of followers
MATTIE.multiplayer.Secondary_Player.prototype.initMembers = function () {
Game_Player.prototype.initMembers.call(this);
this._followers = new MATTIE.multiplayer.NetFollowers(this);
};
MATTIE.multiplayer.Secondary_Player.prototype.performTransfer = function () {
// I dont want to full override this function so instead we can just make the game
// think that the new player never travels to new maps so that the $gameMap.setup() is never called
// this is neccacary to stop players from winding up in the fully hell dimension where the game
// thinks you are on top of every event at once :)
this._newMapId = $gameMap.mapId();
MATTIE.RPG.performTransfer.call(this);
MATTIE.multiplayer.updateEnemyHost();
};
MATTIE.multiplayer.Secondary_Player.prototype.locate = function (x, y) {
Game_Character.prototype.locate.call(this, x, y);
this.center(x, y);
this.makeEncounterCount();
if (this.isInVehicle()) {
this.vehicle().refresh();
}
const leaderX = this.x;
const leaderY = this.y;
this._followers.synchronize(x, y, this.direction(), leaderX, leaderY);
};
/**
*
* @param {*} x target x
* @param {*} y target y
* @param {*} d target dir
* @param {*} leaderX leader x
* @param {*} leaderY leader y
*/
Game_Followers.prototype.synchronize = function (x, y, d, leaderX = null, leaderY = null) {
if (!leaderX) leaderX = $gamePlayer.x;
if (!leaderY) leaderY = $gamePlayer.y;
this.forEach((follower) => {
const dist = Math.sqrt((follower.x - leaderX) ** 2 + (follower.y - leaderY) ** 2);
if (dist > $gameParty.maxBattleMembers() + 1) { // only sync if follower too far away
follower.locate(x, y);
follower.setDirection(d);
}
// else if (dist > 0) {
// let deltaY = y-leaderY;
// let deltaX = x-leaderX;
// console.log("deltaY" + deltaY + "deltax" + deltaX)
// follower.setPosition(follower.x+deltaX,follower.y+deltaY);
// }
}, this);
};
MATTIE.multiplayer.Secondary_Player.prototype.reserveTransfer = function (mapId, x, y, d, fadeType) {
MATTIE.RPG.reserveTransfer.call(this, mapId, x, y, d, fadeType);
};
MATTIE.multiplayer.Secondary_Player.prototype.setActor = function (id) {
if (!this.$netActors.baseActor(id)) this.$netActors.createNewNetActor(id);
this.actorId = id;
};
MATTIE.multiplayer.Secondary_Player.prototype.actor = function () {
return this.$netActors.baseActor(this.actorId);
};
MATTIE.multiplayer.Secondary_Player.prototype.refresh = function () {
var actor = this.$netActors.baseActor(this.actorId);
var characterName = actor ? actor.characterName() : '';
var characterIndex = actor ? actor.characterIndex() : 0;
this.setImage(characterName, characterIndex);
this._followers.refresh();
};
MATTIE.multiplayer.Secondary_Player.prototype.getBattleMembers = function () {
const arr = [];
arr.push(this.$netActors.baseActor(this.actorId));
this._followers.forEach((follower) => {
const actor = follower.actor();
if (actor) arr.push(actor);
});
return arr;
};
MATTIE.multiplayer.Secondary_Player.prototype.center = function (x, y) {
// stop panning camra with netPlayers
};
MATTIE.multiplayer.Secondary_Player.prototype.updateScroll = function (lastScrolledX, lastScrolledY) {
// stop panning camra with netPlayers
};
MATTIE.multiplayer.Secondary_Player.prototype.executeMove = function (direction) {
MATTIE.multiplayer.gamePlayer.executeMove.call(this, direction);
};
MATTIE.multiplayer.Secondary_Player.prototype.startMapEvent = function (x, y, triggers, normal) {
// netplayer started event on the same map as local player
};
/**
* This function is how the movement controller determines if the player should move in a direction when a movement event is triggered.
* Might need to be expanded in future to accommodate gamepads
* @returns
* 0 if not moving
* 2 if down
* 8 if up
* 6 if right
* 4 if left
*/
MATTIE.multiplayer.Secondary_Player.prototype.getInputDirection = function () {
const oldDir4 = this.ctrlDir4;
this.ctrlDir4 = 0;
return oldDir4;
};
//-----------------------------------------
// Game_Player
//----------------------------------------
MATTIE.multiplayer.PlayerModelPerformTransfer = Game_Player.prototype.performTransfer;
Game_Player.prototype.performTransfer = function () {
this.setMapId(this._newMapId);
MATTIE.multiplayer.PlayerModelPerformTransfer.call(this);
};
Game_Player.prototype.setMapId = function (id) {
this._mapId = id;
};
Game_Player.prototype.getMapId = function () {
return this._mapId;
};
/**
* @description check if this player is on the map
* @returns {bool} if this player is on the map
*/
Game_Player.prototype.isOnMap = function () {
return this.getMapId() === $gameMap.mapId();
};
//----------------------------------------
// Game Actor Overrides
//----------------------------------------
MATTIE.multiplayer.Game_ActorsActor = Game_Actors.prototype.actor;
Game_Actors.prototype.actor = function (actorId) {
if (this._data[actorId]) {
if (!this._data[actorId].peerId) {
this._data[actorId].peerId = MATTIE.multiplayer.getCurrentNetController()
? MATTIE.multiplayer.getCurrentNetController().peerId
: false;
}
}
return MATTIE.multiplayer.Game_ActorsActor.call(this, actorId);
};