This is more aimed at making things compatible no matter how the game is played, in a way that is transparent to the developer. It also ensures that those users who choose to play a single player module ( either the OC or another module created by the community using those OC scripts as many seem to do ) with a few friends will not be greeted with strange bugs. Of course those in multiplayer are already dealing with oddball issues since GetFirstPC() is in use throughout the game as it is.
Original code is basically as follows...
void AddEpithetFeat(int nFeatID){ object oPC = GetFirstPC(); object oPartyMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oPartyMember)) { if (GetIsRosterMember(oPartyMember) || GetIsOwnedByPlayer(oPartyMember)) { FeatAdd(oPartyMember, nFeatID, FALSE, TRUE, TRUE); } oPartyMember = GetNextFactionMember(oPC, FALSE); }}Basically the above is only usable in Single player since in multiplayer GetFirstPC() can be someone not even trying to do the quest to begin with as you can have multiple parties. Since this returns a valid result in testing, and probably over half the time in actual mutliplayer play and never in a test module, it lead to very hard to find bugs. To replace this i came up with this, which finds the nearest PC if you are not in single player. I am assuming that if a script is running the player involved is near that script. The parameter allows you to gain some more control of that as well.
/** * Use this instead of GetFirstPC() in modules. When in Single Player it retrieves the player easily as there is only one. However when in multiplayer it is often not clear which player is the correct one so it will get the nearest living player instead. The target parameter allows you to specify who this is close to, otherwise it's object self.** Mainly intended in use for stories and plot related purposes, and allows code which only works in single player to also work in multiplayer** WARNING: do not use in a loop using GetFirstPC() and GetNextPC() as this will cause an infinite loop as each use of GetFirstPC() resets GetNextPC() to start over again.* @author Brian Meyer* @param oTarget ( Default* @return The main player in the module*/object CSLGetMainPC( object oTarget = OBJECT_SELF ){ if ( !GetIsSinglePlayer() ) // not single player then use this { return GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oTarget, CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE); }
return GetFirstPC(); // must be single player}This makes the original function with minor changes work in both multiplayer and single player. Note that it replaces multiple functions which basically do the same thing, both AddEpithetFeat and AddTeamworkFeat are exactly the same with the only difference being the function name.
/** * Adds feat to all members of the players party.* @param iFeatId Identifier of the Feat ( row number in feats.2da )* @param oPC Optional parameter ( normally assume this will not be supplied ) If not supplied then In Single player this is the player starting the game and his party, in multiplayer it's the closest player to where the script is fired.* @see * @replaces AddEpithetFeat, AddTeamworkFeat* @return */void CSLAddFeatToPlayersParty( int nFeatID, object oPC = OBJECT_INVALID ){ if ( !GetIsObjectValid(oPC) ) { oPC = CSLGetMainPC(); } // oTest = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oTarget, 1); object oPartyMember = GetFirstFactionMember(oPC, FALSE); while (GetIsObjectValid(oPartyMember)) { if (GetIsRosterMember(oPartyMember) || GetIsOwnedByPlayer(oPartyMember)) { FeatAdd(oPartyMember, nFeatID, FALSE, TRUE, TRUE); } oPartyMember = GetNextFactionMember(oPC, FALSE); }}
// example usage in ka_banite_bane.nss
// ka_banite_bane// Grants the Bane of the Banites feat.#include "_CSLCore_Feats"
void main(){ CSLAddFeatToPlayersParty(FEAT_EPITHET_BANE_OF_THE_BANITES);}





Retour en haut






