щас выложу свой скрипт спавна
суть простая...
в локе ставятся вейпоинты с определенным тегом и именем
имя имеет вид
SP_SGx_SDy_SNz1-z2_SRn_END
где x - принимает значение 0 (спавнить конкретного моба) или 1 (спавнить моба из группы)
y - задержка между спавнами
z1 и z2 - соответственно минимальное и максимальное количество мобов
n - на каком максимальном расстоянии от вейпоинта может появиться моб
в теге вейпоинта указывается либо тег моба, либо тег группы для спавна
это на OnEnter локи
* при входе игрока запускается псевдохарбит
Neverwinter Script Source
void main()
{
object oArea = GetArea(OBJECT_SELF);
object oPC = GetEnteringObject();
if(GetIsDM(oPC)) return;
if(GetIsPC(oPC)){
int nCount = GetLocalInt(oArea, "nPlayerCount");
nCount++;
SetLocalInt(oArea, "nPlayerCount", nCount);
if(GetLocalInt(oArea, "bNeedSpawn")==FALSE){
SetLocalInt(oArea, "bNeedSpawn", TRUE);
if(GetLocalInt(oArea, "bNeedClear")==FALSE){
ExecuteScript("vr_spawn_general", oArea);
}else{
SetLocalInt(oArea, "bNeedClear", FALSE);
}
}
}
}
это на OnExit локи
* при выходе всех игроков с локи замораживает спавнер, если же выходит моб, то не позволяет ему выйти из локи и возвращает на место спавна
Neverwinter Script Source
void main()
{
object oArea = GetArea(OBJECT_SELF);
object oPC = GetExitingObject();
if(GetIsDM(oPC)) return;
if(GetIsPC(oPC)){
int nCount = GetLocalInt(oArea, "nPlayerCount");
nCount--;
SetLocalInt(oArea, "nPlayerCount", nCount);
if(nCount<=0){ // no PC in location
SetLocalInt(oArea, "bNeedSpawn", FALSE);
object oWP;
int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
int i;
for(i=1; i<=nSpawnersCount; i++){
oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
if(GetLocalInt(oWP, "nChildCount")>0){ // if any spawner has children
SetLocalInt(oArea, "nLastPCExitTime", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
SetLocalInt(oArea, "bNeedClear", TRUE);
break;
}
}
}
}else if(GetIsObjectValid(GetLocalObject(oPC, "parent"))){
//SendMessageToPC(GetFirstPC(), "name="+GetName(oPC));
object oCreature = CreateObject(OBJECT_TYPE_CREATURE,
GetResRef(oPC),
GetLocalLocation(oPC, "lHomeLocation"));
SetLocalLocation(oCreature, "lHomeLocation", GetLocalLocation(oPC, "lHomeLocation"));
DeleteLocalInt(oPC, "TotalDamage");
int i;
for(i=1;i<=GetLocalInt(oPC, "TotalDamagers");i++){
DeleteLocalObject(oPC, "Damager"+IntToString(i));
DeleteLocalInt(oPC, "Damage"+IntToString(i));
}
DeleteLocalInt(oPC, "TotalDamagers");
DeleteLocalInt(oPC, "nPreviousHP");
DeleteLocalObject(oPC, "parent");
DeleteLocalLocation(oPC, "lHomeLocation");
DestroyObject(oPC);
}
}
собственно сам скрипт спавна
*void main() - как раз таки тот самый псевдо харбит, который запускается с частотой, указанной в строках AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
*void CheckWaypoints(object oArea) - проверяет все спавнпоинты в локи и при необходимости их спавнит
*void Spawn(object oWP) - процедура которая непосредственно создает мобов в точках спавна
*void StoreSpawns(object oArea) - срабатывает 1 раз за рестарт... задача его в том, чтобы "расшифровать" тег спавнпоинта и занести все данные в локальные переменные
*void ClearLocationFromCreatures(object oArea) - в случае необходимости деспавна очищает локацию от мобов
Neverwinter Script Source
// SPAWN SYSTEM
// for NWN Shard "Validor 2"
// main script
/* Scripted by Vanes */
#include "vr_spawn_groups"
#include "vr_config"
void CheckWaypoints(object oArea);
void Spawn(object oWP);
void StoreSpawns(object oArea);
void ClearLocationFromCreatures(object oArea);
void main() // psevdo heartbeat
{
object oArea = OBJECT_SELF;
if(GetLocalInt(oArea, "bNeedSpawn")==TRUE){
CheckWaypoints(oArea);
//SendMessageToPC(GetFirstPC(), "attemting to spawn... "+ GetName(oArea));
AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
return;
}
if(GetLocalInt(oArea, "bNeedClear")==TRUE){
//SendMessageToPC(GetFirstPC(), "attemting to clear... "+ GetName(oArea));
//SendMessageToPC(GetFirstPC(), "nLastPCExitTime = " + IntToString(GetLocalInt(oArea, "nLastPCExitTime")));
//SendMessageToPC(GetFirstPC(), "nCurrentTime = " + IntToString(GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")));
if((GetLocalInt(oArea, "nLastPCExitTime")+SPAWN_CLEAR_LOC_DELAY)<=GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")){
//SendMessageToPC(GetFirstPC(), "clearing... "+ GetName(oArea));
ClearLocationFromCreatures(oArea);
SetLocalInt(oArea, "bNeedClear", FALSE);
}else{
AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
}
return;
}
}
void CheckWaypoints(object oArea) // check for WP status (waiting for delay end,
// waiting for children death, need pawn now)
{
if(GetLocalInt(oArea, "bSpawnsStored")==FALSE){
StoreSpawns(oArea);
SetLocalInt(oArea, "bSpawnsStored", TRUE);
}
object oWP;
string sName;
int nPos, nSpawnDelay, nStartDelay, nCurrentTime;
int i;
int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
//SendMessageToPC(GetFirstPC(), "nSpawnersCount="+IntToString(nSpawnersCount));
for(i=1; i<=nSpawnersCount; i++){
oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
sName = GetName(oWP);
//SendMessageToPC(GetFirstPC(), "checking WP " + sName);
if(GetLocalInt(oWP, "nSpawnDelay")==0){ // first check after module started
nPos = FindSubString(sName, "SG");
nSpawnDelay = StringToInt(GetSubString(sName, 5, nPos-6))*60;
//int nTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
//if(nTime!=0){
//SetLocalInt(oWP, "nStartDelay", 60);
SetLocalInt(oWP, "nSpawnDelay", nSpawnDelay);
//}
Spawn(oWP);
}
if(GetLocalInt(oWP, "nChildCount")<=0){
nStartDelay = GetLocalInt(oWP, "nStartDelay");
//SendMessageToPC(GetFirstPC(), "nStartDelay=" + IntToString(nStartDelay));
nCurrentTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
//SendMessageToPC(GetFirstPC(), "nCurrentTime=" + IntToString(nCurrentTime));
nSpawnDelay = GetLocalInt(oWP, "nSpawnDelay");
//SendMessageToPC(GetFirstPC(), "nSpawnDelay=" + IntToString(nSpawnDelay));
if(nSpawnDelay<(nCurrentTime-nStartDelay)){
//SendMessageToPC(GetFirstPC(), "delay end, spawning...");
SetLocalInt(oWP, "bSpawnDisturbed", FALSE);
Spawn(oWP);
}else{
//SendMessageToPC(GetFirstPC(), "waiting for delay end");
}
}
}
}
void Spawn(object oWP)
{
object oCreature;
string sTag;
int nPos1, nPos2;
int n, n1, n2, i, r, r1;
int bGroup = FALSE;
location lLoc;
sTag = GetLocalString(oWP, "sTag"); // for Lexey's Spawn Table
//---- SG flag ----
bGroup = GetLocalInt(oWP, "bGroup");
//---- SRn flag ----
r = GetLocalInt(oWP, "r");
location lLocation = GetLocation(oWP);
object oArea = GetAreaFromLocation(lLocation);
vector vPosition;
float fOrientation = GetFacingFromLocation(lLocation);
//---- SNn flag ----
n1 = GetLocalInt(oWP, "nMin");
n2 = GetLocalInt(oWP, "nMax");
if(n2!=0){
n = n1+Random(n2-n1)+1;
}else{
n = n1;
}
for(i=1; i<=n; i++){
vPosition = GetPositionFromLocation(lLocation);
r1 = Random(r+1);
if(d2()==1) r1 *= -1;
vPosition.x += r1;
r1 = Random(r+1);
if(d2()==1) r1 *= -1;
vPosition.y += r1;
lLoc = Location(oArea, vPosition, fOrientation);
if(bGroup==TRUE) sTag = SpawnGroup(oWP);
oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTag, lLoc);
if(oCreature!=OBJECT_INVALID){
SetLocalInt(oWP, "nChildCount", GetLocalInt(oWP, "nChildCount")+1);
SetLocalObject(oCreature, "parent", oWP);
SetLocalLocation(oCreature, "lHomeLocation", lLoc);
}else{
i--;
}
}
}
void StoreSpawns(object oArea)
{
object oObject = GetFirstObjectInArea(oArea);
string sName, s;
string sTag;
int nPos1, nPos2;
int nCount=0;
while(oObject!=OBJECT_INVALID){
sName = GetName(oObject);
if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)){
nCount++;
SetLocalObject(oArea, "Spawner"+IntToString(nCount), oObject);
SetLocalString(oObject, "sTag", GetTag(oObject));
//---- SG flag ----
nPos1 = FindSubString(sName, "SG");
if((nPos1!=-1)&&(StringToInt(GetSubString(sName, nPos1+2, 1))==1))
SetLocalInt(oObject, "bGroup", TRUE);
//---- SRn flag ----
nPos1 = FindSubString(sName, "SR");
nPos2 = FindSubString(sName, "END");
SetLocalInt(oObject, "r", StringToInt(GetSubString(sName, nPos1+2, nPos2-nPos1-3)));
//---- SNn flag ----
nPos1 = FindSubString(sName, "SN");
nPos2 = FindSubString(sName, "SR");
s = GetSubString(sName, nPos1+2, nPos2-nPos1-3);
nPos1 = FindSubString(s, "-");
if(nPos1==-1){
SetLocalInt(oObject, "nMin", StringToInt(s));
SetLocalInt(oObject, "nMax", 0);
}else{
SetLocalInt(oObject, "nMin", StringToInt(GetSubString(s, 0, nPos1)));
SetLocalInt(oObject, "nMax", StringToInt(GetSubString(s, nPos1+1, GetStringLength(s)-nPos1-1)));
}
}
oObject = GetNextObjectInArea(oArea);
}
SetLocalInt(oArea, "nSpawnersCount", nCount);
}
void ClearLocationFromCreatures(object oArea)
{
string sName;
object oWP;
object oObject = GetFirstObjectInArea(oArea);
while(oObject!=OBJECT_INVALID){
sName = GetName(oObject);
oWP = GetLocalObject(oObject, "parent");
if(oWP!=OBJECT_INVALID)
DestroyObject(oObject);
if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)){
if(GetLocalInt(oObject, "nChildCount")>0){
SetLocalInt(oObject, "nChildCount", 0);
if(GetLocalInt(oObject, "bSpawnDisturbed")){
SetLocalInt(oObject, "nStartDelay", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
}
}
//SendMessageToPC(GetFirstPC(), "b="+IntToString(GetLocalInt(oObject, "bSpawnDisturbed")));
}
oObject = GetNextObjectInArea(oArea);
}
}
ну и последнее... скипт, содержащий таблицу групп мобов...
Neverwinter Script Source
string SpawnGroup(object oWP)
{
string sTag = GetTag(oWP);
if(sTag=="vr_lowlvlgrp1"){
switch(d4()){
case 1: return "vr_badger";
case 2: return "vr_rat";;
case 3: return "vr_direrat";
case 4: return "vr_bat";
}
}
if(sTag=="vr_bugbeargrp"){
int nCount = GetLocalInt(oWP, "nChildCount");
if(nCount<1) return "vr_bugbearhero";
if(nCount<2) return "vr_bugbearshaman";
switch(d2()){
case 1: return "vr_bugbear";
case 2: return "vr_bugbeararcher";
}
}
// ---- !!!! ADD GROUPS OVER THIS LINE !!!! ----
return "";
}