Multiplayer shifter bug
#1
Posté 07 avril 2011 - 07:30
Specifically the bug in question is the on server save, causing a remorph, resulting in loss of merged stats (although the weapons getting permantely merged has also happend at least once recently.)
I found this on the Vault;
http://nwvault.ign.c....Detail&id=2450
but I am wondering if you all have any other suggestions?
Thanks, Laz
#2
Posté 07 avril 2011 - 07:58
IDEA: It would be possible to fix this completely via total polymorph rewrite to use SetAppearance and with NWNX (funcs) but thats not easy. First it takes some time to script it second months to balance it...
#3
Posté 08 avril 2011 - 07:16
It's also quite odd that it happens inconsistantly. Sometime I get the server message in the combat logs "Your character was not saved because it was polymorphed, will try again later" when everything is working properly. But then when the bug occurs I get no message, and just the bug (loss of merged stats.) I think your right on too with it being related to exporting the PC because even when I am not experiencing the bug I can cause it to happen by manually exporting my character while shifted.
Modifié par Lazarus Magni, 08 avril 2011 - 07:21 .
#4
Posté 08 avril 2011 - 09:09
#5
Posté 08 avril 2011 - 10:38
As I said when it is working, and the servers autosave the player gets a message in the combat log saying something to the effect "Character was not saved because it was polymorphed. Will try again soon." When it is not working however, which seems to happen sporadically, it looks like it is exporting the PC, and the bug occurs. I am not sure if I am really explaining it suficiently...
#6
Posté 08 avril 2011 - 10:53
#7
Posté 08 avril 2011 - 10:57
Any other saving of characters is going to be happening from custom scripts added to the module. You should go through them with a fine tooth comb.
As far as using any of Guillies's scripts. I would suggest going through them with a fine tooth comb. Or having someone look at the scripts before using them. Not all of his systems are the best scripting in the world.
#8
Posté 08 avril 2011 - 11:08
They do.Lightfoot8 wrote...
and not to the server vault.
Modifié par ShaDoOoW, 08 avril 2011 - 11:08 .
#9
Posté 08 avril 2011 - 11:45
As far as the manual export, that's not really the problem. Was just a way I could force the bug to happen. If I don't want that to happen I just won't export when polymorphed. The problem is it happening when I don't want it to (sporadically on server saves).
Light, your right, I suspect it is something with the custom scripts, or whatever derivation of Guillies our previous Dev used to try to fix it. Just not sure what to do about it since I am not much of a scripter myself.
Modifié par Lazarus Magni, 08 avril 2011 - 11:47 .
#10
Posté 08 avril 2011 - 11:55
ShaDoOoW wrote...
They do.Lightfoot8 wrote...
and not to the server vault.
Well, I know that the export to the player vault, That is the way I have gotten copys of serveral of my characters that I have played on server vault servers. As far as it also saving it to the server vault, I guess I have to say that I dont really know, I have never tested to see if it saved there also just assumed that it didn't
#11
Posté 09 avril 2011 - 04:00
Have a look at my Fox Spells package.
There is a script in it: fox_export_chars.
Its purpose is to export a player (or also all players).
If a player to export happens to be polymorphed, the script will ensure he retains all item properties.
The opening comment of the script explains its usage.
Hm. That script is practically stand-alone.
You may want to rip it and use it for your module -- no problem.
At best you have to delete a couple references to a constant I define elsewhere.
Nothing you can not handle on your own, I am sure.
-fox
Modifié par the.gray.fox, 09 avril 2011 - 04:04 .
#12
Posté 09 avril 2011 - 07:47
#13
Posté 09 avril 2011 - 08:12
Fox Spells
#14
Posté 09 avril 2011 - 08:22
#15
Posté 12 avril 2011 - 10:59
And sorry for the delay. I am not very much active in internet. But eventually I creep around :-)
The reason I am not releasing my files on the vault is because they are not for everyone. Which is sad.
My project is essentially a framework (or "engine", big fad term everyone likes to speak) to do stuff with the spell system.
So you see, given the nature of Fox Spells, my scripts end up touching "delicate" spots of the game. Good knowledge (at times deep knowledge) of NWN is required to mod Fox Spells.
This is a scripters forums. Of all the users in here, few can effectively take on my project and mod it as they wish (we got two of them right here, I believe. But they are an exception, not the rule). All others will end up asking for help -- or even *much* help.
On top of that I am not the best writer of documentation (english is not even my first language).
I just am not gifted in that department. Although I have stuffed my code with comments, often the comments will not tell all the "fine prints" of the matter at hand. Comments can be no substitute for experience.
Now move all this onto the vault.
Of the large user base there... how many are modders and/or scripters to begin?
And, out of that group, how many are capable ones?
Haha -- Most of them (if not all) would be the same capable people from this very forum.
As far as I understand Fox Spells is already in the best fitting place, you see.
The link is accessible to anybody, and anybody is welcome to mod my project for their own needs.
-fox
#16
Posté 13 avril 2011 - 01:19
#17
Posté 25 avril 2011 - 12:18
the.gray.fox wrote...
Hello.
Have a look at my Fox Spells package.
There is a script in it: fox_export_chars.
Its purpose is to export a player (or also all players).
If a player to export happens to be polymorphed, the script will ensure he retains all item properties.
The opening comment of the script explains its usage.
Hm. That script is practically stand-alone.
You may want to rip it and use it for your module -- no problem.
At best you have to delete a couple references to a constant I define elsewhere.
Nothing you can not handle on your own, I am sure.
-fox
I know your not big on providing advice for modifying your file, but I wonder if you or someone else could elaborate on this? I found the script and looked at it, but not sure which lines I should be deleting...
Thanks, Laz
#18
Posté 25 avril 2011 - 07:27
Here is a standalone version.
// +----------------------+
// | FOX_EXPORT_CHARS.nss |
// +----------------------+
//
// ExportAllCharacters()
// ExportSingleCharacter()
//
// [fox - 25 Apr 2011 - standalone version]
// This script is the solution to the problem of polymorphed PCs losing their
// precious itemproperties after an Export of their Character.
//
// This script is designed to run via ExecuteScript().
// Make it run for a PC for an ExportSingleCharacter().
// Make it run for anything else for an ExportAllCharacters().
// +-----------+
// | CONSTANTS |
// +-----------+
// Name of a LocalObject we set on a polymorphed PC prior to export him. We use
// this to keep, briefly, a reference to all his equipment.
const string sFox_EXPORT_SLOTn = "FOX_EXP_00";
// +------------+
// | PROTOTYPES |
// +------------+
void fox_ExportAllCharacters ();
void fox_ExportSingleCharacter (object oPC);
void fox_ReapplyEnhancements (object oPC);
void fox_RemoveAllItemProperties (object oItem);
void fox_CopyAllItemProperties (object oDest, object oSource);
void main ()
{
/////////////////////////////
// Who are we running for?
object oSelf = OBJECT_SELF;
// Is this a PC?
if (GetIsPC (oSelf))
{
// He is. Attempt to export him alone.
fox_ExportSingleCharacter (oSelf);
}
else
{
// Not a PC. We attempt to export every PC.
fox_ExportAllCharacters ();
}
}
// -----------------------------------------------------------------------------
// Only a helper function to reduce the clutter.
// Cycles through all PCs and export them all.
// -----------------------------------------------------------------------------
void fox_ExportAllCharacters ()
{
////////////////////////////
// Cycle through all PCs.
object oPC = GetFirstPC ();
while (GetIsObjectValid (oPC))
{
fox_ExportSingleCharacter (oPC);
oPC = GetNextPC ();
}
}
// -----------------------------------------------------------------------------
// Only a helper function to reduce the clutter.
// Export the given PC.
// -----------------------------------------------------------------------------
void fox_ExportSingleCharacter (object oPC)
{
// Check if this PC is polymorphed.
int bPoly = FALSE;
effect eSeek = GetFirstEffect (oPC);
while (GetIsEffectValid (eSeek))
{
if (GetEffectType (eSeek) == EFFECT_TYPE_POLYMORPH)
{
bPoly = TRUE;
break;
}
eSeek = GetNextEffect (oPC);
}
////////////////////////////////////////////////////////////////////////////
// If the PC is polymorphed, we create a temporary copy of his current
// equipment. We set a LocalObject on him for each item we create a copy of.
////////////////////////////////////////////////////////////////////////////
if (bPoly)
{
// Sanity check. Is the PC in a valid Area?
if (!GetIsObjectValid (GetArea (oPC)))
{
////////////////////////////////////////////////////////////////////
// There is a period of time, during Area Transitions, in which the
// PC is -technically- outside of the Area he was last in, and not
// yet in the Area he is transitioning to. The length of this window
// depends on the complexity of the Areas involved in the process.
// It is possible that a script executes when the PC is in such a
// no-Area, and any code involving Areas or Locations shall go bug.
////////////////////////////////////////////////////////////////////
// PC is in a no-Area. Quit.
return;
}
// Get the current location of this PC.
location lAt = GetLocation (oPC);
// Scan all equipped items on this polymorphed PC.
int i;
for (i = 0; i < NUM_INVENTORY_SLOTS; ++i)
{
object oEquip = GetItemInSlot (i, oPC);
if (GetIsObjectValid (oEquip))
{
//////////////////////////////////////////////////////
// Create, on ground, a copy of this equipped item.
// -------------------------------------------------------
// NOTE : The copy will stay around for a very brief time.
// Nobody will notice it.
// -------------------------------------------------------
object oCopy = CopyObject (oEquip, lAt, OBJECT_INVALID, "");
if (GetIsObjectValid (oCopy))
{
// Set a reference on the PC to the copy we have made.
SetLocalObject (oPC, sFox_EXPORT_SLOTn + IntToString (i), oCopy);
}
}
}
}
/////////////////////
// Export this PC.
ExportSingleCharacter (oPC);
/////////////////////////////////////////////////////////////////////////
// If the PC is polymorphed, we now reinstate what itemproperties he just
// lost to the export.
/////////////////////////////////////////////////////////////////////////
if (bPoly)
{
DelayCommand (0.1f, fox_ReapplyEnhancements (oPC));
}
}
// -----------------------------------------------------------------------------
// This function takes care to reapply all the enhancements a polymorphed PC had
// at the time of the export of his Character.
// We discovered that, after an export, all equipped items but the Skin/Hide are
// re-spawned anew on the polymorphed PC. Thus we have a set of itemproperties
// that is missing. And there is no way to unequip nor equip items on a PC while
// polymorphed.
// Our solution is to create temporary copies of all items equipped pre-export.
// Then, post-export, we clear the equipped items on the polymorphed PC of all
// their itemproperties. And immediately after we reinstate all itemproperties
// from the copies we made pre-export. This is the only approach that can react
// properly to new properties added to the equipped items after a polymorph.
//
// Our logic is flawless :-)
// -----------------------------------------------------------------------------
void fox_ReapplyEnhancements (object oPC)
{
// Scan all equipped items on this polymorphed PC.
int i;
for (i = 0; i < NUM_INVENTORY_SLOTS; ++i)
{
object oEquip = GetItemInSlot (i, oPC);
if (GetIsObjectValid (oEquip))
{
string sKey = sFox_EXPORT_SLOTn + IntToString (i);
// Get a reference to the temporary copy we made of this item.
object oCopy = GetLocalObject (oPC, sKey);
if (GetIsObjectValid (oCopy))
{
// Delete the reference (we no longer need it).
DeleteLocalObject (oPC, sKey);
// Remove all current itemproperties from the equipped item.
fox_RemoveAllItemProperties (oEquip);
// Copy all itemproperties from the temporary copy.
// (the copy is destroyed within the function)
DelayCommand (0.0f, fox_CopyAllItemProperties (oEquip, oCopy));
}
}
}
}
// -----------------------------------------------------------------------------
// Only a helper function to reduce the clutter.
// Removes ALL itemproperties from the given item.
// -----------------------------------------------------------------------------
void fox_RemoveAllItemProperties (object oItem)
{
itemproperty ipSeek = GetFirstItemProperty (oItem);
while (GetIsItemPropertyValid (ipSeek))
{
RemoveItemProperty (oItem, ipSeek);
ipSeek = GetNextItemProperty (oItem);
}
}
// -----------------------------------------------------------------------------
// Only a helper function to reduce the clutter.
// Copy ALL itemproperties from the Source item to the Destination item.
// -----------------------------------------------------------------------------
void fox_CopyAllItemProperties (object oDest, object oSource)
{
itemproperty ipSeek = GetFirstItemProperty (oSource);
while (GetIsItemPropertyValid (ipSeek))
{
AddItemProperty (DURATION_TYPE_PERMANENT, ipSeek, oDest, 0.0f);
ipSeek = GetNextItemProperty (oSource);
}
// Destroy the Source item.
// (that is, the temporary copy item we made)
DestroyObject (oSource, 0.0f);
}
-fox
- KMdS! aime ceci
#19
Posté 25 avril 2011 - 10:29
Modifié par Lazarus Magni, 25 avril 2011 - 10:30 .
#20
Posté 26 avril 2011 - 12:17
Lazarus Magni wrote...
That's fantastic Grey Fox, thank you so much! So this should work on it's own without any further editing?
Yes. It is a self-contained standalone script. Ready as-is.
To be run through ExecuteScript().
The Object you run it for dictates the work mode (ExportSingleCharacter() vs. ExportAllCharacters() ).
Run it for a Player to export that very Player alone.
Run it for any object other than a Player (example: the Module or a sword) to export all Players.
NOTE : This script is not to be used in conjunction with Fox Spells. First: it would not compile. Second: Fox Spells uses its own original and equivalent version of this one. So... keep the two things separate.
-fox
[edit]
Hm. By the way...
18 days ago ShaDoOoW wrote...
[...] The manual saving via Export Character button should be avoided, [...] because it allows exploits [...]
The exploit he refers to is the instant refill of HP and THP in case the Player polymorphed to a creature who received Temporary Hit Points. Most polymorph shapes do this.
Said exploit is easily defeated. Zero away the THP bonus defined in polymorph.2da.
Then have your polymorph script take care to apply said THP bonus using EffectTemporaryHitpoints().
Doing so the export process shall not refill HP nor THP -- so defeating any malicious use of manual exports.
There would be more to tell about polymorphs, but I would go off topic.
If you want to learn all details, have a look at my polymorph system within Fox Spells.
-fox
Modifié par the.gray.fox, 26 avril 2011 - 01:52 .
#21
Posté 26 avril 2011 - 07:19
#22
Posté 27 avril 2011 - 02:19
*This assumes the file name for fox's function is fox_export_chars
I think that would cover it.
btw Fox, thanks for this, I'll be working this into the server I play since we suffer from a similar issue.
Modifié par Terrorble, 27 avril 2011 - 02:20 .
#23
Posté 27 avril 2011 - 06:54
http://nwvault.ign.c...=198735&id=3773
That is what we used to fix this most recently I believe. I have forwarded this info to the server host, and hopefully he will try one or both of these solutions out soon.
Thanks for all the help everyone.
Laz





Retour en haut







