じ☆ve冰风 发表于 2026-7-29 16:45:57

Spawn.js, a simple event spawner

Introduction:
This plugin provide several functions to spawn or copy events.

spawnEvent(which,tag, x, y,d)
Spawn an event at location x, y
Parameters:
which: the event template, see 'Event template' below
tag: if a dead event contains this tag string in its note, it will be revived instead, and 'which' will be ignored unless the dead event is not found. By default, an event is dead if its _erased property is true. If tag is false, the function will not try to find a dead event and always spawn a new one. If tag is a function, it will be used to search for a dead entity using its own rule. The function must have a parameter which is the event to be tested, if the entity is dead the funcion should return true, otherwise it returns false.
x, y: location of the spawned event. Optional.
d: direction of the spawned event. Optional.

replaceEvent(e1,e2)
Replace event e1 with e2. An event using 'Event template' e2 will be spawned and replace event e1.

Game_Event.setPreserved(preserved)
Set if the event is preserved. A preserved event will not reset if the player leaves current map and returns.
Parameter preserved should be a boolean value.

Game_Event.isPreserved()
Check if the event is preserved.

Game_Event.reload()
Reload current event. If the event is foreign, it will use it's original position in the foreign map. If the event has been replaced, the original event will be loaded instead. Notice this is a 'had reset', so everything including self switches will be reset.

$E(which)
Return an event, parameter 'which' should be in the format of 'Event template', see below.

$spr(which)
Return an event's sprite, parameter 'which' should be in the format of 'Event template', see below. This is not part of the spawn functions, but just in case the sprite is changed for some reason.

Event template:
Any event from the map editor can be used as template to spawn.
When using as a parameter, it can be any of the format below:

[*]Event id: it should be an integer.
[*]Event name: a string indicating the name of the event, if multiple events have the same name, the first one will be used.
[*]Event tag: if name is not found, the function will try to find the string inside the note property. A tag can be any string, but it is recommended to use html like tags.
[*]Event object: You can provide an event object to copy from
[*]Object with an eventId method. Usually it means an Game_Interpreter object, so you can use 'this' as parameter in an event command script.
[*]Event from another map: This is only used by spawnEvent function. An event from a foreign map will be spawned in current map, and can be preserved if you use setPreserved to change it's preserved property. In this case, the parameter should be a string in the form of 'event@map'. 'event' can be either id, name or tag. 'map' can be either map id, filename, or map name. For example, '1@Map001', 'cat@1', '<dog>@village_of_fire'...
Source code:
Spoiler: source                JavaScript:       
//=============================================================================
// Spawn.js
//=============================================================================

/*:
* @plugindesc Spawn or copy events from current and other maps
* @author utunnels
*
* @help This plugin provide several functions to spawn or copy events.

spawnEvent(which,tag, x, y,d)
Spawn an event at location x, y
Parameters:
which: the event template, see 'Event template' below
tag: if a dead event contains this tag string in its note,
it will be revived instead, and 'which' will be ignored unless
the dead event is not found. By default, an event is dead if
its _erased property is true. If tag is false, the function will
not try to find a dead event and always spawn a new one.
If tag is a function, it will be used to search for a dead entity
using its own rule. The function must have a parameter which is
the event to be tested, if the entity is dead the funcion should
return true, otherwise it returns false.
x, y: location of the spawned event.
d: direction of the spawned event.

replaceEvent(e1,e2)
Replace event e1 with e2. An event using 'Event template' e2 will
be spawned and replace event e1.

Game_Event.setPreserved(preserved)
Set if the event is preserved. A preserved event will not reset
if the player leaves current map and returns.
Parameter preserved should be a boolean value.

Game_Event.isPreserved()
Check if the event is preserved.

Game_Event.reload()
Reload current event. If the event is foreign, it will use it's
original position in the foreign map. If the event has been replaced,
the original event will be loaded instead. Notice this is a 'had reset',
so everything including self switches will be reset.

$E(which)
Return an event, parameter 'which' should be in the format of
'Event template', see below.

$spr(which)
Return an event's sprite, parameter 'which' should be in the
format of 'Event template', see below.

Event template:
Any event from the map editor can be used as template to spawn.
When using as a parameter, it can be any of the format below:
1. Event id: it should be an integer.
2. Event name: a string indicating the name of the event,
if multiple events have the same name, the first one will be used.
3. Event tag: if name is not found, the function will try to find
the string inside the note property. A tag can be any string, but
it is recommended to use html like tags.
4. Event object: You can provide an event object to copy from
5. Object with an eventId method. Usually it means an Game_Interpreter,
So you can use 'this' as parameter in an event command script.
6. Event from another map: This is only used by spawnEvent function.
An event from a foreign map will be spawned in current map, and can be
preserved if you use setPreserved to change it's preserved property.
In this case, the parameter should be a string in the form of 'event@map'.
'event' can be either id, name or tag. 'map' can be either map id, filename,
or map name. For example, '1@Map001', 'cat@1', '<dog>@village_of_fire'...
*/
Game_Event.prototype.originalEventId = function() {
    return this._originalEventId||this._eventId;
};

Game_Event.prototype.event = function() {
    var e = $dataMap.events;
    if(!e){
      if(this._foreignMapId){
      e=this.reloadForeignEvent();
      }
    }
    return e;
};

Game_Event.prototype.reloadForeignEvent=function(){
var fmapid = this._foreignMapId,feid=this._foreignEventId,slot=this.originalEventId();
var map = loadMapJSONSync(fmapid);
var e = map.events
e = JSON.parse(JSON.stringify(e));
$dataMap.events = e;
return e;
};

Game_Event.prototype.reload = function() {
var thismap = loadMapJSONSync($gameMap.mapId());
var eid = this.eventId();
var oid = this.originalEventId();
if(!thismap.events){
    if(!$dataMap.events){
      this.reloadForeignEvent();
    }
    replaceEvent(this,oid,true);
}else{
    replaceEvent(this,eid,true);
}
$gameSelfSwitches.setValue([$gameMap.mapId(),eid,'A'],false);
$gameSelfSwitches.setValue([$gameMap.mapId(),eid,'B'],false);
$gameSelfSwitches.setValue([$gameMap.mapId(),eid,'C'],false);
$gameSelfSwitches.setValue([$gameMap.mapId(),eid,'D'],false);
};

$mapCache = {};

//Load a file from data folder, synchronous
//Replace this with node fs version if necessary
function loadDataJSONSync(filename){
var src = filename+'.json';
var xhr = new XMLHttpRequest(), result=null;
xhr.open('GET', 'data/' + src, false); xhr.overrideMimeType('application/json');
xhr.onload = function() {
    if (xhr.status == 200) {
      result = JSON.parse(xhr.responseText);
    } else {
      console.log('xhr status: ' + xhr.status + ', ' + filename);
    }
};
xhr.send();
return result;
}

function loadMapJSONSync(mapId){
var filename;
if(/Map/.test(mapId)){//Map117
    filename = mapId;
}else if(!isNaN(mapId)){//117
    filename = 'Map%1'.format(mapId.padZero(3));
}else{//map name
    var mi = $dataMapInfos.findIndex(function(m){return m&&m.name==mapId;});
    if(mi>0){
      filename = 'Map%1'.format(mi.padZero(3));
    }else{
      return null;
    }
}
var map = $mapCache;
if(!map){
    var map = loadDataJSONSync(filename);
    if(!map) return null;
    $mapCache = map;
    map.id = Number(filename.substring(3));
}
return map;
}

function readForeignEventInfo(which){
var ns = which.split('@');
var map = loadMapJSONSync(ns);
fmapid = map.id;
var e = map.events]||map.events.find(function(e){return e&&e.name==ns;})||map.events.find(function(e){return e&&e.note.contains(ns);})||null;
e.mapId = fmapid;
return e;
}

function copyEvent(which,newonly){
var fmapid,feid;
if(typeof which=='string'&&which.contains('@')){
    var e = readForeignEventInfo(which);
    var slot;
    if(e){
      if(e.mapId!=$gameMap.mapId()){
      fmapid = e.mapId;
      feid = e.id;
      var fe = $gameMap._events.find(function(e){return e&&e._foreignMapId==fmapid&&e._foreignEventId==e.id;});
      if(fe) slot = fe.originalEventId();
      else{
          slot = $gameMap._events.length;
          e = JSON.parse(JSON.stringify(e));
          $dataMap.events = e;
      }
      which = e.id = slot;
      }else{
      which = e.id;
      }
    }else{
      throw "copyEvent: event not found - " + which;
    }
}
if(typeof which!='number'){
    var we = $E(which);
    if(we){
      which = we.originalEventId();
    }else{
      we = $dataMap.events.find(function(e){return e&&e.name==which;})||$dataMap.events.find(function(e){return e&&e.note.contains(which);});
      if(!we){
      throw 'copyEvent: event not found - ' + which;
      }
      which = we.id;
    }
}
var freeid = $gameMap._events.findIndex(function(ev,i){return i>0&&!ev;});
freeid = freeid>0?freeid:$gameMap._events.length;
var event = new Game_Event($gameMap._mapId, which);
event._foreignMapId = fmapid||0;
event._foreignEventId = feid||0;
event._eventId = freeid;
event._originalEventId = which;
if(newonly) return event;
$gameMap._events=event;
event.refresh();
var spr = new Sprite_Character(event);
SceneManager._scene._spriteset._characterSprites.push(spr);
SceneManager._scene._spriteset._tilemap.addChild(spr);
return event;
}

function spawnEvent(which,tag, x, y, d){
var es = null;
if(tag===false){
    // do not revive 'dead' events, always copy
}else{
    //search for a dead event and revive it
    if(typeof tag=='function'){
      //tag as searh function
      es = $gameMap.events().find(tag);
    }else{
      if(tag){
      //find a dead event with the specific tag
      es = $gameMap._events.find(function(e){return e&&e._erased&&e.event().note.contains(tag);});
      }
      if(!es){
      //find a dead event with the same copy
      if(typeof which=='string'&&which.indexOf('@')>0){
      }else{
          var ee = $E(which);
          es = $gameMap._events.find(function(e){return e&&e._erased&&e.originalEventId()==ee.originalEventId();});
      }
      }
    }
}
if(es) {
    es._erased=false;
    es._moveRoute = null;
    delete es._isPreserved;
    for(var k in $gameSelfSwitches._data){
      var kk,A,B,C,D; eval('kk=['+k+']');
      if(kk==$gameMap.mapId()&&kk==es.eventId()){
      delete $gameSelfSwitches._data;
      }
    }
    //need to reset sprite if you have played with it
    //delete es.shiftY;
    //$spr(es).scale.set(1,1);
    //$spr(es).rotation=0;
    //$spr(es).anchor.set(0.5,1);
    es.refresh();
}else{
    es = copyEvent(which);
}
if(typeof x!='undefined'){
    es._x = es._realX = x;
}
if(typeof y!='undefined'){
    es._y = es._realY = y;
}
if(typeof d!='undefined'){
    es._direction = d;
}
return es;
}

function replaceEvent(e1, e2, reset){
e1 = $E(e1);
e2 = copyEvent(e2, true);
e2._eventId = e1._eventId;
if(!reset){
    e2._x = e1._x;
    e2._y = e1._y;
    e2._direction=e1._direction;
    e2._realX = e1._realX;
    e2._realY = e1._realY;

    e2._opacity = e1._opacity;
    e2._blendMode = e1._blendMode;
    e2._pattern = e1._blendMode;
    e2._transparent = e1._transparent;
    e2._bushDepth = e1._bushDepth;
    e2._animationId = e1._animationId;
    e2._balloonId = e1._balloonId;
    e2._animationPlaying = e1._animationPlaying;
    e2._balloonPlaying = e1._balloonPlaying;
    e2._animationCount = e1._animationCount;
    e2._stopCount = e1._stopCount;
    e2._jumpCount = e1._jumpCount;
    e2._jumpPeak = e1._jumpPeak;
    e2._movementSuccess = e1._movementSuccess;
}
for(var k in e1) delete e1;
Object.assign(e1,e2);
//e1.setupPage();
e1.refresh();
}

//preserve event when map changes
Game_Event.prototype.setPreserved = function(p) {
    this._isPreserved = p;
};

Game_Event.prototype.isPreserved = function() {
    return this._isPreserved;
};

var gp_performTransfer = Game_Player.prototype.performTransfer;
Game_Player.prototype.performTransfer = function() {
if (this.isTransferring()) {
    $gameSystem.savePreservedEvents();
}
gp_performTransfer.call(this);
};

Game_System.prototype.savePreservedEvents = function(){
this._preservedEvents = this._preservedEvents||[];
var mid = $gameMap.mapId();
this._preservedEvents = [];
$gameMap.events().forEach(function(e){
    if(e._isPreserved){
      $gameSystem._preservedEvents.push(e);
    }
});
};

var gm_setupEvents = Game_Map.prototype.setupEvents;
Game_Map.prototype.setupEvents = function() {
    gm_setupEvents.call(this);
    //copy preserved events back
    if($gameSystem._preservedEvents){
      $gameSystem._preservedEvents.forEach((function(e){
      this._events = e;
      }).bind(this));
    }
    this.refreshTileEvents();
};

//////////////////////////////////////////////////////////////////////

function $E(n){
if(n instanceof Game_Event) return n;
if(typeof n.eventId=='function') n = n.eventId();
return $gameMap._events||$gameMap._events.find(function(e){return e&&e.event().name==n;})||$gameMap._events.find(function(e){return e&&e.event().note.contains(n);})||null;
}

function $spr(c){
if(c instanceof Game_Character == false){
    c = $E(c);
}
if(!c) return null;
return SceneManager._scene._spriteset._characterSprites.find(function(s){return s._character==c;});
}


///////////////////////////////event layer/////////////////////////////

function makeEventLayer(e){
e = $E(e);
var spr = $spr(e);

if(spr._madeEventLayerSprite) return;

e.screenX = function(){
    var tw = $gameMap.tileWidth();
    return Math.round(this.scrolledX() * tw+(this.layerX||0));
};
e.screenY = function() {
      var th = $gameMap.tileHeight();
      return Math.round(this.scrolledY() * th - this.jumpHeight() + (this.layerY||0));
};

e.screenZ = function() {
      return this.z==undefined?(this._priorityType * 2 + 1):this.z;
};

spr._madeEventLayerSprite = true;
spr.anchor.set(0,0);
spr.updateCharacterFrame = function(){
    var c = this._character;
    if(c.frameX!=undefined){
      this.setFrame(c.frameX,c.frameY,c.frameWidth,c.frameHeight);
    }else{
      this.setFrame(0,0,this.bitmap.width,this.bitmap.height);
    }
};
}

////////////////////////////////////video player///////////////////////////////////////////

function makeEventVideo(e,name,x,y,w,h){
if(e.video){
    e.video.pause();
}
//makeEventLayer(e);
var spr = $spr(e);
spr.updateCharacterFrame();
x = x||0;
y=y||0;
w=w||spr.width;
h=h||spr.height;
var vp = 'movies/';
var v = document.createElement('video');
var s1 = document.createElement('source');
s1.type = 'video/webm';
s1.src = vp + name + '.webm';
var s2 = document.createElement('source');
s2.type = 'video/mp4';
s2.src = vp + name + '.mp4';
v.autoplay=false;
v.append(s1,s2);
v.autoplay=false;
v.preload=true;
v.loop=true;
v.play();
var bitmap = new Bitmap(w,h);
var sspr = new Sprite(bitmap);
sspr.video = v;
spr.x = x;
spr.y = y;
sspr.anchor = spr.anchor;
spr.removeChildren();
spr.addChild(sspr);
sspr.update = function(){
    this.bitmap.canvas.getContext('2d').drawImage(this.video,0,0,this.width,this.height);
    this.bitmap._setDirty();
    Sprite.prototype.update.call(this);
}
e.video = v;
}


Terms of use:
You can use it in any project, credit is not required.

Download link and sample:
See the attachment. It provides a sample project which uses Spawn.js


本贴来自国际rpgmaker官方论坛作者:utunnels处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/spawn-js-a-simple-event-spawner.170655/
页: [1]
查看完整版本: Spawn.js, a simple event spawner