|
Post by loudent2 on Oct 11, 2008 12:58:15 GMT -5
Can you explain what you mean by this. I'm not sure we're having the same conversation anymore
|
|
|
Post by DEV Driller on Oct 11, 2008 18:44:23 GMT -5
I would use the date function to control treasure chests. Much more efficient. -driller Well, loot indeed must be separately spawned in a PW, to avoid any form of exploiting. What I am doing to reset loot in chests is this: // Generates 2 low treasure items, respawns content every hour #include "NW_O2_CONINCLUDE" void main() { float fDelay = 3600.0; if (GetLocalInt(OBJECT_SELF,"NW_DO_ONCE") != 0) { return; } object oLastOpener = GetLastOpener(); GenerateLowTreasure(oLastOpener, OBJECT_SELF); GenerateLowTreasure(oLastOpener, OBJECT_SELF); SetLocalInt(OBJECT_SELF,"NW_DO_ONCE",1); DelayCommand(fDelay,SetLocalInt(OBJECT_SELF,"NW_DO_ONCE",0)); } Something like that should work, my only doubt is if DelayCommand is an efficient function or not.
|
|
|
Post by DEV Driller on Oct 11, 2008 19:03:01 GMT -5
OT, I wrote a better and simpler spawn system, you should have the code in the module I sent. It was called monster_spawn It gets rid of the list script and put the variables on the spawner itself, which is much easier, you don't have to recompile when you add mobs either. It will be easy to expand it to do others things also. Here is the code if you don't have it. -driller #include "nw_i0_plot"
void TrashObject(object obj) { if(GetIsPC(obj)) return; // if this is not a container, just destroy it and we're done if(GetIsPC(GetItemPossessor(obj))) return; if (GetHasInventory(obj) == FALSE) DestroyObject(obj); else { object oItem = GetFirstItemInInventory(obj); // destroy everything in the inventory first
while (oItem != OBJECT_INVALID) { TrashObject(oItem); oItem = GetNextItemInInventory(obj); } // destroy the container itself DestroyObject(obj); } }
void CleanUp() { object oArea = GetArea(OBJECT_SELF);
object oObject = GetFirstObjectInArea(oArea); string sName; while(GetIsObjectValid(oObject)) {
sName = GetName(oObject); if(!GetIsPC(oObject)) {
if(sName == "Remains" || (GetObjectType(oObject) == OBJECT_TYPE_ITEM && !GetIsPC(GetItemPossessor(oObject)) ) ) TrashObject(oObject);
oObject = GetNextObjectInArea(oArea); }
} }
//Cache WPs int CacheSpawnPoints() { int nCount = GetLocalInt(OBJECT_SELF,"WP_COUNT"); int i;
if(nCount == 0) { object oWP = GetFirstObjectInArea(); while(GetIsObjectValid(oWP)) { if(GetTag(oWP) == "WP_SPAWN") i++; SetLocalObject(OBJECT_SELF,"WP_"+IntToString(i),oWP); oWP = GetNextObjectInArea(); } //Cache SetLocalInt(OBJECT_SELF,"WP_COUNT",i); }
return nCount; }
location GetRandomWPLocation() {
if(GetLocalInt(OBJECT_SELF,"INIT") != 1) { SetLocalInt(OBJECT_SELF,"INIT",1); CacheSpawnPoints(); } int i = Random( GetLocalInt(OBJECT_SELF,"WP_COUNT") ) + 1; return GetLocation(GetLocalObject(OBJECT_SELF,"WP_"+IntToString(i))); }
//Target string, text to split the string at, direction Right = 0, Left = 1 string SpiltTxt(string sString, string sSplit, int nDir);
string SpiltTxt(string sString, string sSplit, int nDir) { int nLength = GetStringLength(sString); int nPos = FindSubString(sString,sSplit);
if(nDir == 0) return GetStringRight(sString,nLength-(nPos+1));
if(nDir == 1) return GetStringLeft(sString,nPos);
return ""; }
void SpawnMobs(string sResRef, int nCount) {
int i; for(i=1;i<=nCount;i++) { object oMob = GetLocalObject(OBJECT_SELF,sResRef+IntToString(i)); if(!GetIsObjectValid(oMob)) { oMob = CreateObject(OBJECT_TYPE_CREATURE,sResRef,GetRandomWPLocation()); SetLocalObject(OBJECT_SELF,sResRef+IntToString(i),oMob); } //Set Local Scripts here SetLocalString(oMob,"DeathScript","mob_death");
AssignCommand(oMob,ActionRandomWalk()); }
}
void main() { if(!GetIsObjectValid(GetNearestPC())) CleanUp();
int i = 1; int nCount; string sResRef;
string sString = GetLocalString(OBJECT_SELF,IntToString(i));
while(sString != "") { nCount = StringToInt(SpiltTxt(sString,":",0)); sResRef = SpiltTxt(sString,":",1); SpawnMobs(sResRef, nCount); i++; sString = GetLocalString(OBJECT_SELF,IntToString(i)); }
}
[quote author="@otomotetsuo" timestamp="1223692490" source="/post/9527/thread"]Creature spawning is the mmorpg_spawner system. I am currently working on a sister system to that one for lootable spawning. :) The prototype is already finished.
Creature spawning is the mmorpg_spawner system. I am currently working on a sister system to that one for lootable spawning. The prototype is already finished. Creature spawning is the mmorpg_spawner system. I am currently working on a sister system to that one for lootable spawning. The prototype is already finished. -OT
|
|
|
Post by otomotetsuo on Oct 11, 2008 19:58:33 GMT -5
@// Generates 2 low treasure items **GenerateLowTreasure and similar are not necessarily going to create single items. They just spawn a low quantity of a low valued variety of items or gp. But you still could get something like 5gp and a Thief tool from a single call of the GenerateLowTreasure function.** @delaycommand is an efficient function or not Your options are not really unlimited in this respect. But one alternative is to create a time stamp instead. The advantage of a time stamp based function over a DelayCommand one is that there is nothing left running once the check and possible loot creation function has run. It's just goes: OpenChest; TimeCheck; YesLoot-TimeStamp OR NoLoot-EndScript; and it's done. HTH -OT **EDIT** DEV Driller"I would use the date function to control treasure chests." Beat me to it ... "Here is the code if you don't have it." Thank you.
|
|
davidb
Senior Member
Posts: 300
|
Post by davidb on Oct 12, 2008 11:38:15 GMT -5
Great advice, I will use Date too...
Now, back on resetting a zone, I think I've dealt with the trap thing at least, which was the most difficult one... I have now a script that respawns every trap in the zone, based in Waypoints.
My idea is to place it in the Enter event, but it should be fired only when the zone is empty when a PC enters it ¿How can I perform this check?
Additionally, I am thinking in the possibility to run this script every Xminutes, is there a way to do this, avoiding the heartbeat script?
|
|
|
Post by otomotetsuo on Oct 12, 2008 12:16:01 GMT -5
Well. One way that you could go about it is to use a tag team of your OnEnter, OnExit and OnHearbeat scripts for the Area itself. The basic idea would be:
-OnEnter Is Condition True? - If Yes-EndScript OR If No Set Condition True.
-OnHeartbeat Is Condition True? - If Yes-ResetStuff AND Set Condition False OR If No - EndScript.
-OnExit IsPcStillHere? - If Yes-EndScript OR If No- Set Condition False. (OR You could just delete the variable Once the area is empty. It is always a good idea to delete any variables that are no longer needed. And honestly, avoiding setting them persistently is the absolute best way to go.)
The most likely kind of variable that you would be looking to set/get for these is a local one set to the area itself.
-OT
|
|
davidb
Senior Member
Posts: 300
|
Post by davidb on Oct 12, 2008 13:56:13 GMT -5
Yes Otomo, but what I actually don't know how to do is to write a function that actually tells me if there is a PC in the zone. Must I go object by object checking if it's a PC, is that the way?
HeartBeat I've read is highly inefficient in PWs, but surely if it isn't, is the most obvious event to use...
|
|
|
Post by loudent2 on Oct 12, 2008 13:56:42 GMT -5
So, I'm just going to hop in here real quick and make a recomendation. You should just grab the latest version of NESS. It handles mob, placable and trap spawning with a great deal of options. I can also be used to spawn ligts and place effects (as well is items). It has a built in loot system and is very extensible. There's no reason for you guys to be re-writing all this stuff from scratch.
|
|
davidb
Senior Member
Posts: 300
|
Post by davidb on Oct 12, 2008 15:03:19 GMT -5
I will check it, loudent. Thanks.
However, one of my goals is learning how to use the toolset, that's why I am trying to write my own code. But looking at NESS surely will help me a lot too.
|
|
|
Post by loudent2 on Oct 12, 2008 15:08:36 GMT -5
latest version is is at: www.chunkychode.com/ness . Under files/Links you'll want "Full Ness import .erf for NWN2 v2.3a" The manual was written for NWN1 but carries over pretty well. Only difference is you use resource name instead of resref when specifying what to spawn. It can be also found there in zip and .pdf format: "NESS_v80_Tutorial_v11.pdf/zip" NESS bioware guild with information: nwn.bioware.com/guilds_registry/viewguild.html?gid=9354(Disclaimer: Although I would recomend it even if it were not the case, I handle the NWN2 modifications for the NESS spawner (but am not the original author))
|
|
|
Post by DEV Driller on Oct 12, 2008 16:34:50 GMT -5
Heartbeats are fine, especially with modern CPUs. Thanks, -driller Yes Otomo, but what I actually don't know how to do is to write a function that actually tells me if there is a PC in the zone. Must I go object by object checking if it's a PC, is that the way? HeartBeat I've read is highly inefficient in PWs, but surely if it isn't, is the most obvious event to use...
|
|
|
Post by DEV Driller on Oct 12, 2008 17:00:47 GMT -5
If you want to check if a PC is in an area do this: int GetPCIsInArea(object oArea) { object oObject = GetFirstObjectInArea(oArea);
if(!GetIsPC(oObject)) oObject = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oObject);
return GetIsPC(oObject); } -driller Yes Otomo, but what I actually don't know how to do is to write a function that actually tells me if there is a PC in the zone. Must I go object by object checking if it's a PC, is that the way? HeartBeat I've read is highly inefficient in PWs, but surely if it isn't, is the most obvious event to use...
|
|
davidb
Senior Member
Posts: 300
|
Post by davidb on Oct 13, 2008 5:01:28 GMT -5
Heartbeats are fine, especially with modern CPUs. Even in PWs, are you sure? does this PW, for example, use heartbeat script usually? Because what I have read in tutoriasl or boards is, heartbeat=big processor load. Thanks for the GetNearestCreature function, that's the final piece I needed for my small puzzle. And yet another question, I hope I'm not bothering you too much... if I place that function in OnExit script, it will run before the PC leaves (thus resulting always in one PC found)? and if I place it OnEnter, will it catch the PC that is entering, or run right before he enters? My trap spawn function is working very well, BTW... you can place traps at defined locations, or semi-randomize them, even gauging their overall difficulty and types. Very customizable. BTW, to Josh, please create a scripting subforum... we're mixing half a dozen things just in one thread... pretty please
|
|
|
Post by DEV Driller on Oct 13, 2008 6:07:48 GMT -5
Yes I am sure. Heartbeats got a bad name back in 2002 when NWN first came out, the CPUs of that time along with people trying to use heartbeats to do all kinds of crazy stuff gave it a bad reputation. CPUs have much more power now and people know how to use nwscript more efficiently. Ad for the enter/exit question. I am pretty sure that it will return FALSE, I don't think the PC is a valid object in the area when those event scripts fire. -driller Heartbeats are fine, especially with modern CPUs. Even in PWs, are you sure? does this PW, for example, use heartbeat script usually? Because what I have read in tutoriasl or boards is, heartbeat=big processor load. Thanks for the GetNearestCreature function, that's the final piece I needed for my small puzzle. And yet another question, I hope I'm not bothering you too much... if I place that function in OnExit script, it will run before the PC leaves (thus resulting always in one PC found)? and if I place it OnEnter, will it catch the PC that is entering, or run right before he enters? My trap spawn function is working very well, BTW... you can place traps at defined locations, or semi-randomize them, even gauging their overall difficulty and types. Very customizable. BTW, to Josh, please create a scripting subforum... we're mixing half a dozen things just in one thread... pretty please
|
|
|
Post by otomotetsuo on Oct 13, 2008 6:25:27 GMT -5
@even in PWs, are you sure? does this PW, for example, use heartbeat script usually? Heartbeat scripts can be used, davidb, just not ABused, and yes, we use them. If you hook a large amount of intense functions onto the heartbeat event you will see a hit on performance. The rule of thumb is that, if you can get away with not using the heartbeat script to do something then do it.
There is one other practice that I like to use for making sure that my hearbeat scripts don't run a second longer than they have to. For example, a HB script that resets a trap when a player is inside the area - if a player never sets foot in that area, the only thing that script should do on heartbeat is to check to see if there is a player in the area ... (or a variable value that is created by an OnEnter check that rings true for PC). That script can run a thousand times, every six seconds, just doing that one variable check and cause no discernable performance hit.
It is when you attach some kind of long complicated sequence of events and chained scripts and bla and bla and bla ... when you boil it down ... you want the script to get in and get out of running mode as fast as possible. If you can find a master condition that the whole script really relies on - then place that condition check right at the beginning ... if it is not met, you haven't wasted any processor power.
@onexit Will not find any PC's in the area if the exiting creature was the last PC in that area. (And if that is specifically what condition you are checking at that time.)
@onenter Will be called once the EnteringObject has entered. (This is to say that you will not miss the PC entering because the script fired a moment too soon.)
Keep em coming, this is good exercise.
-OT
|
|