Changed: Merge changes from next patch

This commit is contained in:
kervala 2011-05-31 21:51:26 +02:00
parent 42f302c0aa
commit 37cfa5a9f2
43 changed files with 2325 additions and 132 deletions

View file

@ -9006,6 +9006,14 @@ void CCharacterCL::setAuraFX(uint index, const CAnimationFX *sheet)
if (sheet == NULL)
{
std::list<CAttachedFX::CBuildInfo>::iterator itAttachedFxToStart = _AttachedFXListToStart.begin();
while(itAttachedFxToStart != _AttachedFXListToStart.end())
{
if ((*itAttachedFxToStart).MaxNumAnimCount == index)
itAttachedFxToStart = _AttachedFXListToStart.erase(itAttachedFxToStart);
else
++itAttachedFxToStart;
}
// if there's already an aura attached, and if it is not already shutting down
if (_AuraFX[index] && _AuraFX[index]->TimeOutDate == 0.f)
{

View file

@ -2497,7 +2497,9 @@ class CAHAddShape : public IActionHandler
{
shape = sShape.substr(0, index);
sShape = sShape.substr(index+1);
} else {
}
else
{
shape = sShape;
have_shapes = false;
}

View file

@ -2052,7 +2052,8 @@ void getItemText (CDBCtrlSheet *item, ucstring &itemText, const CItemSheet*pIS)
case ITEMFAMILY::CONSUMABLE :
{
strFindReplace(itemText, "%consumption_time", toString(pIS->Consumable.ConsumptionTime));
strFindReplace(itemText, "%overdose_timer", toString(pIS->Consumable.OverdoseTimer/60));
strFindReplace(itemText, "%overdose_timer_min", toString(pIS->Consumable.OverdoseTimer/60));
strFindReplace(itemText, "%overdose_timer_sec", toString(pIS->Consumable.OverdoseTimer % 60));
// Get Item Consumable infos
CItemConsumableEffectHelper::getInstance()->getItemConsumableEffectText(pIS, itemText, item->getQuality());
}

View file

@ -2095,13 +2095,13 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti
rVR.draw11RotFlipBitmap (_RenderLayer, x, y, 0, false, _DispOverBmpId, armourCol);
// decal layer because must drawn after Items/Brick in DXTC
// NB: use OverColor, not Over2Color here. Because of hack in updateArmourColor()
rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOverColor));
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOverColor));
}
else
{
// decal layer because must drawn after Items/Brick in DXTC
rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, _DispOverBmpId, fastMulRGB(curSheetColor, _IconOverColor));
rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOver2Color));
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOverBmpId, fastMulRGB(curSheetColor, _IconOverColor));
rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOver2Color));
}
// Draw Quality. -1 for lookandfeel. Draw it with global color

View file

@ -871,6 +871,13 @@ void CGroupHTML::beginElement (uint element_number, const BOOL *present, const c
{
_TextColor.push_back(_TextColor.empty() ? CRGBA::White : _TextColor.back());
}
if (present[HTML_FONT_SIZE] && value[HTML_FONT_SIZE])
{
uint fontsize;
fromString(value[HTML_FONT_SIZE], fontsize);
_FontSize.push_back(fontsize);
}
}
break;
case HTML_BR:
@ -1407,6 +1414,7 @@ void CGroupHTML::endElement (uint element_number)
{
case HTML_FONT:
popIfNotEmpty (_TextColor);
popIfNotEmpty (_FontSize);
break;
case HTML_A:
popIfNotEmpty (_TextColor);
@ -2251,8 +2259,9 @@ void CGroupHTML::addImage(const char *img, bool globalColor)
else*/
getParagraph()->addChild(newImage);
paragraphChange ();
} else {
}
else
{
//
// 2/ if it doesn't work, try to load the image in cache
//
@ -3394,7 +3403,8 @@ int CGroupHTML::luaInsertText(CLuaState &ls)
ucstring text;
text.fromUtf8(ls.toString(2));
if (!_Forms.empty()) {
if (!_Forms.empty())
{
for (uint i=0; i<_Forms.back().Entries.size(); i++)
{
if (_Forms.back().Entries[i].TextArea && _Forms.back().Entries[i].Name == name)
@ -3438,11 +3448,14 @@ int CGroupHTML::luaAddImage(CLuaState &ls)
paragraphChange();
}
string url = getLink();
if (!url.empty()) {
if (!url.empty())
{
string params = "name=" + getId() + "|url=" + getLink ();
addButton(CCtrlButton::PushButton, ls.toString(1), ls.toString(1), ls.toString(1),
"", ls.toBoolean(2), "browse", params.c_str(), "");
} else {
}
else
{
addImage(ls.toString(1), ls.toBoolean(2));
}

View file

@ -277,7 +277,7 @@ string CGroupHTMLWebIG::home ()
void CGroupHTMLWebIG::handle ()
{
Home = "http://atys.ryzom.com/start/index.php";
// Home = "http://atys.ryzom.com/start/index.php";
CGroupHTML::handle ();
}

View file

@ -133,8 +133,8 @@ void CItemConsumableEffectHelper::getItemConsumableEffectText(const CItemSheet *
strFindReplace(result, "%minutes", toString(duration/60));
strFindReplace(result, "%secondes", toString(duration%60));
strFindReplace(result, "%radius", toString(radius));
strFindReplace(result, "%targetDisableTime", toString(targetDisableTime));
strFindReplace(result, "%userDisableTime", toString(userDisableTime));
strFindReplace(result, "%targetDisableTime", "0");
strFindReplace(result, "%userDisableTime", "0");
effects += result;
effects += "\n";
@ -183,12 +183,12 @@ void CItemConsumableEffectHelper::getItemConsumableEffectText(const CItemSheet *
fromString(params[4].c_str(), userDisableTime);
ucstring result = CI18N::get("uiItemConsumableEffectStaminaAura");
strFindReplace(result, "%modifier", toString(regenMod));
strFindReplace(result, "%modifier", toString(bonus));
strFindReplace(result, "%minutes", toString(duration/60));
strFindReplace(result, "%secondes", toString(duration%60));
strFindReplace(result, "%radius", toString(radius));
strFindReplace(result, "%targetDisableTime", toString(targetDisableTime));
strFindReplace(result, "%userDisableTime", toString(userDisableTime));
strFindReplace(result, "%targetDisableTime", "0");
strFindReplace(result, "%userDisableTime", "0");
effects += result;
effects += "\n";
@ -240,8 +240,8 @@ void CItemConsumableEffectHelper::getItemConsumableEffectText(const CItemSheet *
strFindReplace(result, "%minutes", toString(duration/60));
strFindReplace(result, "%secondes", toString(duration%60));
strFindReplace(result, "%radius", toString(radius));
strFindReplace(result, "%targetDisableTime", toString(targetDisableTime));
strFindReplace(result, "%userDisableTime", toString(userDisableTime));
strFindReplace(result, "%targetDisableTime", "0");
strFindReplace(result, "%userDisableTime", "0");
effects += result;
effects += "\n";

View file

@ -503,7 +503,6 @@ void CSPhraseManager::updateMemoryDBAll()
for(uint i=0;i<PHRASE_MAX_MEMORY_SLOT;i++)
{
_MemoryDbLeaves[i]->setValue32(0);
_MemoryAltDbLeaves[i]->setValue32(0);
}
}
else
@ -515,7 +514,14 @@ void CSPhraseManager::updateMemoryDBAll()
_MemoryDbLeaves[i]->setValue32(0);
else
_MemoryDbLeaves[i]->setValue32(slot.Id);
}
}
if(_SelectedMemoryDB != -1 && (sint32)_Memories.size() > 0)
{
// Always update alt gestionsets
for(uint i=0;i<PHRASE_MAX_MEMORY_SLOT;i++)
{
CMemorySlot &slotAlt= _Memories[0].Slot[i];
if(!slotAlt.isPhrase())
_MemoryAltDbLeaves[i]->setValue32(0);

View file

@ -15,10 +15,10 @@ addSkillPoints :DEV:SGM:GM:EM: // Add skill points of given type (Fight=0, M
addXPToSkill :DEV:SGM:GM:EM: // Gain experience in the given skill: <xp> <skill> [<count>]
broadcast :DEV:SGM:GM:EM:VG: // Broadcast a message: [repeat=<num repeat> or during=<time in seconds>] [every=<delay in secondes>] <message>
changeHairCut :DEV:SGM:GM:EM: // Change the haircut of a player: <sheet name>
changeMode :DEV:SGM:GM: // Change mode of a player: <mode>
changeVar :DEV:SGM:GM: // Change a variable of a player: <var> <val>
changeMode :DEV:SGM:GM:EM: // Change mode of a player: <mode>
changeVar :DEV:SGM:GM:EM: // Change a variable of a player: <var> <val>
checkTargetSP :DEV:SGM:GM: // Check target player skill points
clearEventFaction :DEV:SGM:GM: // Clear the event faction of player: <player name>
clearEventFaction :DEV:SGM:GM:EM: // Clear the event faction of player: <player name>
clearFriendsList :DEV:SGM:GM: // Clear the friend list of a player
clearGuildMessage // Clear the guild message of the day
clearIgnoreList :DEV:SGM:GM: // Clear the ignore list of a player
@ -36,8 +36,8 @@ dodge // Set the defense mode to dodge
execPhrase :DEV:SGM:GM: // Execute a phrase with given bricks: <cyclic 0/1> [<brick ids>...]
executeSabrinaPhrase :DEV:SGM:GM: // Execute a sabrina phrase: <cyclic 0/1> <phraseId>
failMission :DEV:SGM:GM: // Force mission failure: <mission idx>
forceTargetToDie :DEV:SGM:GM: // Force entity target to die
getEventFaction :DEV:SGM:GM: // Get the event faction of player: <player name>
forceTargetToDie :DEV:SGM:GM:EM: // Force entity target to die
getEventFaction :DEV:SGM:GM:EM: // Get the event faction of player: <player name>
giveRespawnPoint :DEV:SGM:GM: // Give a respawn point to a player: <respawn point name>
guildInvite // Send a guild invite to a player character without distance constrainte
roomInvite // Send a room invite
@ -59,7 +59,7 @@ loadFromXML :DEV:SGM: // Load a character from an XML file: <file name>
logXpGain :DEV:SGM:GM: // Log or not xp gain infos for specified player: <on/off>
lPosFlags :DEV:SGM:GM:VG:SG:G:EM:EG: // List position flags (short format): [<radius in meters>]
monitorMissions :DEV:SGM:GM: // Monitor missions of the given player: <player name>
motd :DEV:SGM:GM:VG: // Set the current message of the day: <message to be displayed>
motd :DEV:SGM:GM:EM:VG: // Set the current message of the day: <message to be displayed>
mute :DEV:SGM:GM:EM:VG:SG: // Mute a user: <player name> <duration>
muteUniverse :DEV:SGM:GM:EM:VG:SG: // Mute the universe channel: <duration>
outpostBanGuild :DEV:SGM:GM:EM: // Ban a guild for an outpost conflit: <outpost_id> <guild_name> [<all|atk|def>]
@ -70,14 +70,14 @@ parry // Set the defense mode to parry
progressMission :DEV:SGM:GM: // Force mission progression: <mission idx> [repeat]
renameGuild :DEV:SGM:GM:EM: // Rename a guild: <guild name> <new guild name>
renamePlayer [SU] :DEV:SGM:GM:EM: // Rename a player: <player name> <new playerName>
renamePlayerForEvent :DEV:SGM:EM:EG: // Rename a player temporarily for an event: <player name> <new playerName>
resetPowerFlags :DEV:SGM:GM: // Reset the ineffective aura and the power flags for given character
renamePlayerForEvent :DEV:SGM:GM:EM:EG: // Rename a player temporarily for an event: <player name> <new playerName>
resetPowerFlags :DEV:SGM:GM:EM: // Reset the ineffective aura and the power flags for given character
respawnAfterDeath // Respawn after death at re-spawn point name, it must be valid (validated by PC and usable): <Respawn idx>
resurrected // Another PC resurrect PC by giving some energy: <Hp> <Sta> <Sap> <Focus>
root :DEV:SGM:GM:EM:VG:SG: // Root a player: <player name> <time in seconds>
saveToPDR :DEV:SGM: // Save a character to a binary PDR file: <file name>
saveToXML :DEV:SGM: // Save a character to an XML file: <file name>
setEventFaction :DEV:SGM:GM: // Set the event faction of player: <player name> <event faction>
setEventFaction :DEV:SGM:GM:EM: // Set the event faction of player: <player name> <event faction>
setGMGuild :DEV:SGM:GM: // Set the current GM guild
setGuildChargePoint :DEV:SGM:GM:EM: // Set the charge points of a guild: <guild name> <points>
setGuildDescription :DEV:SGM:GM:EM: // Set a guild description: <guild name> <new guild description>
@ -90,13 +90,16 @@ setPvPTag // Set player character PvP tag to true or false
setSkillsToMaxValue :DEV:SGM:GM:EM: // Set player skills to max value
showCSR :DEV:SGM:GM:VG:SG:G:EM:EG: // Show CSR title if the player is a CSR
showFBT :DEV:SGM:GM:EM: // Show Focus Beta Tester title if the player is a FBT
startEvent :DEV:SGM:GM: // Start an event with the given name: <event name>
startEvent :DEV:SGM:GM:EM: // Start an event with the given name: <event name>
stopEvent :DEV:SGM:GM:EM: // Stop previous started event
stopMonitorMissions :DEV:SGM:GM: // Stop monitoring missions of the given player
summon :DEV:SGM:GM:VG:SG:EM: // Summon a player in front of the CSR: <player name>
targetInfos :DEV:SGM:GM:EM: // Give infos on the target
teamInvite // Send a team invite to a player character
connectUserChannel // Connect to User Channel Chat
webExecCommand // Execute web command (need HMAC signature)
webDelCommandsIds // Delete web transactions for web_app
webAddCommandsIds // Add web command transactions for web_app
teleport :DEV:SGM:GM:VG:SG:G:OBSERVER:EM:EG: // Teleport the CSR in front of a player: <player name>
tpPosFlag :DEV:SGM:GM:VG:SG:G:EM:EG: // Teleport a player to a position flag: <flag name>
universe :DEV:SGM:GM:EM: // Chat in universe mode: <boolean>
@ -113,8 +116,8 @@ addFactionAttackableToTarget :DEV: // add attackable possibility for player o
forceMissionProgress :DEV: // force mission step progression (for debug purpose only)
savePlayerActiveChar :DEV:SGM: // save immediatly a player active char, a specific filename can enter for backup a character in specific situation/context
reloadPlayer :DEV:SGM: // set next filename used for loading a character (must be offline and log later) or relaod an online character to previous backup or with a specified filename.
farTPPush :DEV:SGM:GM:VG:SG: // used to tp on a specific session
farTPReturn :DEV:SGM:GM:VG:SG: // used to tp back to your previous session
farTPPush :DEV:SGM:GM:VG:SG:EM: // used to tp on a specific session
farTPReturn :DEV:SGM:GM:VG:SG:EM: // used to tp back to your previous session
characterMissionDump :DEV:SGM:GM: //Dump mission list for a character
removeMission :DEV:SGM:GM: //Remove a mission of a character
addMission :DEV:SGM:GM: //add a mission to a character
@ -135,11 +138,12 @@ Name :DEV:SGM:GM:EM: // Name of a player
Position :DEV:SGM:GM:VG:PR:OBSERVER:EM:EG: // Position of a player (in meters) <posx>,<posy>[,<posz>]] | <bot name> | <player name> | home
Priv :DEV: // User privilege
PriviledgePVP :DEV:SGM:GM:EM:EG: // Turns PVP on/off on character (blame coder for typo)
RyzomDate :DEV:SGM:GM: // Current ryzom date
RyzomTime :DEV:SGM:GM: // Current ryzom time
RyzomDate :DEV:SGM:GM:EM: // Current ryzom date
RyzomTime :DEV:SGM:GM:EM: // Current ryzom time
// Event commands
eventCreateNpcGroup :DEV:SGM:GM:EM: // Create a npc group
eScript :DEV:SGM:GM:EM: // Execute a script on an event npc group (new version)
eventNpcGroupScript :DEV:SGM:GM:EM: // Execute a script on an event npc group
eventSetBotName :DEV:SGM:GM:EM: // Set the name of a bot
eventSetBotScale :DEV:SGM:GM:EM: // Set the scale of a bot
@ -155,3 +159,4 @@ eventSetBotFaction :DEV:SGM:GM:EM: // Changes the faction of a bot: <faction
eventSetBotFameByKill :DEV:SGM:GM:EM: // Changes the amount of fame earned for bot faction when killing it: <fame value>
eventSetBotURL :DEV:SGM:GM:EM: // Set the url of a bot
eventSetBotURLName :DEV:SGM:GM:EM: // Set the url name of a bot
eventSpawnToxic :DEV:SGM:GM:EM: // Add toxic cloud

View file

@ -68,6 +68,9 @@ CAIInstance::~CAIInstance()
static bool zoneHaveError = false;
/// map of lastCreatedNpcGroup by player id
static std::map<CEntityId, string> _PlayersLastCreatedNpcGroup;
void CAIInstance::addZone(string const& zoneName, CNpcZone* zone)
{
#if !FINAL_VERSION
@ -850,12 +853,14 @@ void cbEventCreateNpcGroup( NLNET::CMessage& msgin, const std::string &serviceNa
sint32 orientation;
uint32 nbBots;
NLMISC::CSheetId sheetId;
CEntityId playerId;
double dispersionRadius;
bool spawnBots;
std::string botsName;
msgin.serial(messageVersion);
nlassert(messageVersion==1);
msgin.serial(instanceNumber);
msgin.serial(playerId);
msgin.serial(x);
msgin.serial(y);
msgin.serial(orientation);
@ -867,7 +872,11 @@ void cbEventCreateNpcGroup( NLNET::CMessage& msgin, const std::string &serviceNa
CAIInstance* instance = CAIS::instance().getAIInstance(instanceNumber);
if (instance)
{
instance->eventCreateNpcGroup(nbBots, sheetId, CAIVector((double)x/1000., (double)y/1000.), dispersionRadius, spawnBots, (double)orientation/1000., botsName);
CGroupNpc* npcGroup = instance->eventCreateNpcGroup(nbBots, sheetId, CAIVector((double)x/1000., (double)y/1000.), dispersionRadius, spawnBots, (double)orientation/1000., botsName);
if (npcGroup != NULL)
{
_PlayersLastCreatedNpcGroup[playerId] = npcGroup->getName();
}
}
}
@ -882,12 +891,56 @@ void cbEventNpcGroupScript( NLNET::CMessage& msgin, const std::string &serviceNa
msgin.serial(messageVersion);
nlassert(messageVersion==1);
msgin.serial(nbString);
strings.resize(nbString);
nlinfo("Event group script with %d strings", nbString);
for (uint32 i=0; i<nbString; ++i)
string eid;
string firstCommand;
msgin.serial(eid); // Player or boteid
msgin.serial(firstCommand); // Player or boteid
if (firstCommand[0] == '(') // Old eventNpcGroupScript command : (boteid, commands...)
{
msgin.serial(strings[i]);
nlinfo(" %d '%s'", i, strings[i].c_str());
nlinfo("Event group script with %d strings :", nbString);
strings.resize(nbString);
strings[0] = eid;
nlinfo(" %d '%s'", 0, strings[0].c_str());
strings[1] = firstCommand;
nlinfo(" %d '%s'", 1, strings[1].c_str());
for (uint32 i=2; i<nbString-2; ++i)
{
msgin.serial(strings[i]);
nlinfo(" %d '%s'", i, strings[i].c_str());
}
}
else
{
nlinfo("Event group script with %d strings :", nbString-1);
CEntityId playerId(eid);
strings.resize(nbString-1);
NLMISC::CSString groupname = CSString(firstCommand);
if (firstCommand[0] == '#' && firstCommand[1] == '(')
{
NLMISC::CEntityId botEId = NLMISC::CEntityId(firstCommand.substr(1));
if (botEId==NLMISC::CEntityId::Unknown)
return;
CAIEntityPhysical* entity = CAIEntityPhysicalLocator::getInstance()->getEntity(botEId);
CSpawnBotNpc* bot = dynamic_cast<CSpawnBotNpc*>(entity);
if (!bot)
return;
if (!bot->getPersistent().getOwner())
return;
strings[0] = bot->getPersistent().getOwner()->getName();
}
else
{
strings[0] = (string)groupname.replace("#last", _PlayersLastCreatedNpcGroup[playerId].c_str());
}
nlinfo(" %d '%s'", 0, strings[0].c_str());
for (uint32 i=1; i<nbString-1; ++i)
{
msgin.serial(strings[i]);
nlinfo(" %d '%s'", i, strings[i].c_str());
}
}
scriptCommands2.push_back(strings);
}

View file

@ -4421,14 +4421,20 @@ void getCurrentSpeakerEid__s(CStateInstance* entity, CScriptStack& stack)
return;
}
//////////////////////////////////////////////////////////////////////////////
// Undocumented methods //
//////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// CGroup
/** @page code
@subsection setSheet_s_
Change the sheet of a creature
Arguments: -> s(sheetName)
@code
()setSheet('ccdeb2');
@endcode
*/
void setSheet_s_(CStateInstance* entity, CScriptStack& stack)
{
string sheetname = stack.top();
@ -4450,8 +4456,23 @@ void setSheet_s_(CStateInstance* entity, CScriptStack& stack)
}
}
/****************************************************************************/
//----------------------------------------------------------------------------
// CGroup
/** @page code
@subsection setHealer_f_
Make the group healer (need test)
Arguments: -> f(isHealer)
@code
()setHealer(1);
@endcode
*/
void setHealer_f_(CStateInstance* entity, CScriptStack& stack)
{
bool value = ((float)stack.top())!=0.f;

View file

@ -295,6 +295,7 @@ void setActivity_s_(CStateInstance* entity, CScriptStack& stack)
spawnGroup->activityProfile().setAIProfile(new CGrpProfileBandit(spawnGroup));
break;
}
nlwarning("trying to set activity profile to an unknown profile name");
}
}
@ -402,6 +403,106 @@ void stopMoving__(CStateInstance* entity, CScriptStack& stack)
spawnGroup->movingProfile().setAIProfile(new CGrpProfileIdle(spawnGroup));
}
//----------------------------------------------------------------------------
/** @page code
@subsection startWander_f_
Set activity to wander in current pos:
Arguments: f(Radius) ->
@param[in] Radius dispersion of wander activity
@code
()startWander(100); // Gives a wander activity to the group with dispersion of 100
@endcode
*/
// Spawned CGroupNpc not in a family behaviour
void startWander_f_(CStateInstance* entity, CScriptStack& stack)
{
uint32 dispersionRadius = (uint32)(float&)stack.top();
stack.pop();
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
if (!aiInstance)
return;
if (!entity) { nlwarning("setActivity failed!"); return; }
CGroupNpc* group = dynamic_cast<CGroupNpc*>(entity->getGroup());
if (!group)
{ nlwarning("startWander failed: no NPC group");
return;
}
CSpawnGroupNpc* spawnGroup = group->getSpawnObj();
if (!spawnGroup)
{ nlwarning("startWander failed: no spawned group");
return;
}
CAIVector centerPos;
if (!spawnGroup->calcCenterPos(centerPos)) // true if there's some bots in the group.
{ nlwarning("startWander failed: no center pos");
return;
}
NLMISC::CSmartPtr<CNpcZonePlaceNoPrim> destZone = NLMISC::CSmartPtr<CNpcZonePlaceNoPrim>(new CNpcZonePlaceNoPrim());
destZone->setPosAndRadius(AITYPES::vp_auto, CAIPos(centerPos, 0, 0), (uint32)(dispersionRadius*1000.));
spawnGroup->movingProfile().setAIProfile(new CGrpProfileWanderNoPrim(spawnGroup, destZone));
}
//----------------------------------------------------------------------------
/** @page code
@subsection startMoving_fff_
Set activity to wander in current pos:
Arguments: f(Radius) ->
@param[in] Radius dispersion of wander activity
@code
()startWander(100); // Gives a wander activity to the group with dispersion of 100
@endcode
*/
// Spawned CGroupNpc not in a family behaviour
void startMoving_fff_(CStateInstance* entity, CScriptStack& stack)
{
uint32 dispersionRadius = (uint32)(float&)stack.top();
stack.pop();
float const y = (float&)stack.top();
stack.pop();
float const x = (float&)stack.top();
stack.pop();
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
if (!aiInstance)
return;
if (!entity) { nlwarning("setActivity failed!"); return; }
CGroupNpc* group = dynamic_cast<CGroupNpc*>(entity->getGroup());
if (!group)
{ nlwarning("setActivity failed: no NPC group");
return;
}
CSpawnGroupNpc* spawnGroup = group->getSpawnObj();
if (!spawnGroup)
{ nlwarning("setActivity failed: no spawned group");
return;
}
NLMISC::CSmartPtr<CNpcZonePlaceNoPrim> destZone = NLMISC::CSmartPtr<CNpcZonePlaceNoPrim>(new CNpcZonePlaceNoPrim());
destZone->setPosAndRadius(AITYPES::vp_auto, CAIPos(CAIVector(x, y), 0, 0), (uint32)(dispersionRadius*1000.));
spawnGroup->movingProfile().setAIProfile(new CGrpProfileWanderNoPrim(spawnGroup, destZone));
return;
}
//----------------------------------------------------------------------------
/** @page code
@ -2284,7 +2385,7 @@ void emote_css_(CStateInstance* entity, CScriptStack& stack)
//CBot& bot = spawnBot->getPersistent();
// The entity Id must be valid (whe know that the bot is alive so its entity Id must be ok)
// The entity Id must be valid (we know that the bot is alive so its entity Id must be ok)
NLMISC::CEntityId entityId=spawnBot->getEntityId();
if (entityId == NLMISC::CEntityId::Unknown)
{
@ -2342,6 +2443,105 @@ void emote_ss_(CStateInstance* entity, CScriptStack& stack)
NLNET::CUnifiedNetwork::getInstance()->send( "EGS", msgout );
}
void emote_s_(CStateInstance* entity, CScriptStack& stack)
{
string emoteName = (string)stack.top(); stack.pop();
// Is the emote valid
uint32 emoteId = CAIS::instance().getEmotNumber(emoteName);
if (emoteId == ~0)
return;
// Get the behaviour Id
MBEHAV::EBehaviour behaviourId = (MBEHAV::EBehaviour)(emoteId + MBEHAV::EMOTE_BEGIN);
CGroup* group = entity->getGroup();
if (group->isSpawned())
{
FOREACH(itBot, CCont<CBot>, group->bots())
{
CBot* bot = *itBot;
if (bot)
{
// Change the behaviour
if (bot->isSpawned())
{
CSpawnBot *spawnBot = bot->getSpawnObj();
if (spawnBot)
{
CEntityId botId = spawnBot->getEntityId();
NLNET::CMessage msgout("SET_BEHAVIOUR");
msgout.serial(botId);
MBEHAV::CBehaviour bh(behaviourId);
bh.Data = (uint16)(CTimeInterface::gameCycle());
msgout.serial(bh);
NLNET::CUnifiedNetwork::getInstance()->send( "EGS", msgout );
}
}
}
}
}
}
void rename_s_(CStateInstance* entity, CScriptStack& stack)
{
string newName = (string)stack.top(); stack.pop();
CGroup* group = entity->getGroup();
if (group->isSpawned())
{
FOREACH(itBot, CCont<CBot>, group->bots())
{
CBot* bot = *itBot;
if (bot)
{
if (bot->isSpawned())
{
CSpawnBot *spawnBot = bot->getSpawnObj();
if (spawnBot)
{
TDataSetRow row = spawnBot->dataSetRow();
ucstring name;
name.fromUtf8(newName);
NLNET::CMessage msgout("CHARACTER_NAME");
msgout.serial(row);
msgout.serial(name);
sendMessageViaMirror("IOS", msgout);
}
}
}
}
}
}
void vpx_s_(CStateInstance* entity, CScriptStack& stack)
{
string vpx = (string)stack.top(); stack.pop();
CGroup* group = entity->getGroup();
if (group->isSpawned())
{
FOREACH(itBot, CCont<CBot>, group->bots())
{
CBotNpc* bot = NLMISC::safe_cast<CBotNpc*>(*itBot);
if (bot)
{
bot->setVisualProperties(vpx);
bot->sendVisualProperties();
}
}
}
}
//----------------------------------------------------------------------------
/** @page code
@ -2446,6 +2646,8 @@ std::map<std::string, FScrptNativeFunc> nfGetNpcGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, setFactionProp_ss_);
REGISTER_NATIVE_FUNC(functions, moveToZone_ss_);
REGISTER_NATIVE_FUNC(functions, setActivity_s_);
REGISTER_NATIVE_FUNC(functions, startWander_f_);
REGISTER_NATIVE_FUNC(functions, startMoving_fff_);
REGISTER_NATIVE_FUNC(functions, waitInZone_s_);
REGISTER_NATIVE_FUNC(functions, stopMoving__);
REGISTER_NATIVE_FUNC(functions, wander__);
@ -2481,6 +2683,9 @@ std::map<std::string, FScrptNativeFunc> nfGetNpcGroupNativeFunctions()
REGISTER_NATIVE_FUNC(functions, facing_cscs_);
REGISTER_NATIVE_FUNC(functions, emote_css_);
REGISTER_NATIVE_FUNC(functions, emote_ss_);
REGISTER_NATIVE_FUNC(functions, emote_s_);
REGISTER_NATIVE_FUNC(functions, rename_s_);
REGISTER_NATIVE_FUNC(functions, vpx_s_);
REGISTER_NATIVE_FUNC(functions, npcSay_css_);
REGISTER_NATIVE_FUNC(functions, dssMessage_fsss_);
REGISTER_NATIVE_FUNC(functions, despawnBotByAlias_s_);

File diff suppressed because it is too large Load diff

View file

@ -152,7 +152,7 @@ void CRoomInstancePlayer::removeUser( CCharacter* user )
msgout.serial(phrase);
sendMessageViaMirror("IOS", msgout);
uint32 titleId = STRING_MANAGER::sendStringToUser(userId, "ANSWER_OK", titleParams);
uint32 titleId = STRING_MANAGER::sendStringToUser(userId, "web_transactions", titleParams);
uint32 textId = STRING_MANAGER::sendStringToUser(userId, "CLOSE_URL", textParams);
PlayerManager.sendImpulseToClient(user->getId(), "USER:POPUP", titleId, textId);
@ -195,7 +195,7 @@ void CRoomInstancePlayer::addUser( CCharacter* user, CCharacter* owner )
msgout.serial(phrase);
sendMessageViaMirror("IOS", msgout);
uint32 titleId = STRING_MANAGER::sendStringToUser(userId, "ANSWER_OK", titleParams);
uint32 titleId = STRING_MANAGER::sendStringToUser(userId, "web_transactions", titleParams);
uint32 textId = STRING_MANAGER::sendStringToUser(userId, "RYZHOME_URL", textParams);
PlayerManager.sendImpulseToClient(user->getId(), "USER:POPUP", titleId, textId);

View file

@ -3073,7 +3073,7 @@ void cbClientEventSetItemCustomText( NLNET::CMessage& msgin, const std::string &
CCharacter* character = PlayerManager.getChar(eid);
if(!character) return;
if (!character->havePriv(":DEV:SGM:EM:"))
if (!character->havePriv(":DEV:SGM:GM:EM:"))
{
// it should be the crafter of the item, check
if (inventory==INVENTORIES::UNDEFINED) return;
@ -3111,6 +3111,10 @@ void cbClientEventSetItemCustomText( NLNET::CMessage& msgin, const std::string &
return;
}
// prevent use of @WEB at begin
if (text.size() >= 4 && text[0]=='@' && text[1]=='W' && text[2]=='E' && text[3]=='B')
text = text.substr(4, text.size() - 4);
// force that the begin of the text for non admin is %mfc
if(!text.empty() && text.substr(0, 4) != ucstring("%mfc"))
{

View file

@ -429,6 +429,7 @@ void CCreature::initFormPointer(NLMISC::CSheetId sheetId)
if (_UserModelId.empty() || _PrimAlias == 0)
{
_Form = CSheets::getCreaturesForm( sheetId );
_SheetName = sheetId.toString();
}
else
{
@ -1703,7 +1704,10 @@ void CCreature::kill(TDataSetRow killerRowId)
{
if( killer != this && killer->getId().getType() != RYZOMID::player )
{
PROGRESSIONPVE::CCharacterProgressionPVE::getInstance()->removeCreature(_EntityRowId);
if (_SheetName.size() != 15 || (_SheetName.size() == 15 && _SheetName[5] != '5' && _SheetName[5] != '6' && _SheetName[5] != '7'))
PROGRESSIONPVE::CCharacterProgressionPVE::getInstance()->removeXpCreature(_EntityRowId);
else
PROGRESSIONPVE::CCharacterProgressionPVE::getInstance()->removeCreature(_EntityRowId);
}
else if( killer != this )
{

View file

@ -552,6 +552,8 @@ private:
/// keep pointer on creature form
const CStaticCreatures * _Form;
std::string _SheetName;
uint32 _Faction;
bool _FameByKillValid;
sint32 _FameByKill;

View file

@ -1309,6 +1309,16 @@ void addParam(const std::string &paramStr, std::vector<TBrickParam::IIdPtr> &Par
Params.push_back(new CSBrickParamLifeAura(tail));
break;
case TBrickParam::SP_LIFE_AURA2:
// $*STRUCT CSBrickParamLifeAura2 TBrickParam::SP_LIFE_AURA2
// $*-i uint16 RegenMod // regen modifier (in %) proportionally to item level
// $*-f float Duration // duration in seconds
// $*-f float Radius // aura radius in meters
// $*-f float TargetDisableTime // disable life aura for x seconds on targets
// $*-f float UserDisableTime // disable life aura for x seconds on user
Params.push_back(new CSBrickParamLifeAura2(tail));
break;
case TBrickParam::SP_STAMINA_AURA:
// $*STRUCT CSBrickParamStaminaAura TBrickParam::SP_STAMINA_AURA
// $*-i uint16 RegenMod // regen modifier (in %)
@ -1319,6 +1329,16 @@ void addParam(const std::string &paramStr, std::vector<TBrickParam::IIdPtr> &Par
Params.push_back(new CSBrickParamStaminaAura(tail));
break;
case TBrickParam::SP_STAMINA_AURA2:
// $*STRUCT CSBrickParamStaminaAura2 TBrickParam::SP_STAMINA_AURA2
// $*-i uint16 RegenMod // regen modifier (in %) proportionally to item level
// $*-f float Duration // duration in seconds
// $*-f float Radius // aura radius in meters
// $*-f float TargetDisableTime // disable life aura for x seconds on targets
// $*-f float UserDisableTime // disable life aura for x seconds on user
Params.push_back(new CSBrickParamStaminaAura2(tail));
break;
case TBrickParam::SP_SAP_AURA:
// $*STRUCT CSBrickParamSapAura TBrickParam::SP_SAP_AURA
// $*-i uint16 RegenMod // regen modifier (in %)
@ -1329,6 +1349,16 @@ void addParam(const std::string &paramStr, std::vector<TBrickParam::IIdPtr> &Par
Params.push_back(new CSBrickParamSapAura(tail));
break;
case TBrickParam::SP_SAP_AURA2:
// $*STRUCT CSBrickParamSapAura2 TBrickParam::SP_SAP_AURA2
// $*-i uint16 RegenMod // regen modifier (in %) proportionally to item level
// $*-f float Duration // duration in seconds
// $*-f float Radius // aura radius in meters
// $*-f float TargetDisableTime // disable life aura for x seconds on targets
// $*-f float UserDisableTime // disable life aura for x seconds on user
Params.push_back(new CSBrickParamSapAura2(tail));
break;
case TBrickParam::SP_SPEEDING_UP:
// $*STRUCT CSBrickParamSpeedingUp TBrickParam::SP_SPEEDING_UP
// $*-i uint16 SpeedMod // speed modifier (in %)

View file

@ -123,8 +123,11 @@ public:
SP_TAUNT,
SP_SHIELDING,
SP_LIFE_AURA,
SP_LIFE_AURA2,
SP_STAMINA_AURA,
SP_STAMINA_AURA2,
SP_SAP_AURA,
SP_SAP_AURA2,
SP_SPEEDING_UP,
SP_INVULNERABILITY,
SP_MELEE_PROTECTION_AURA,
@ -299,8 +302,11 @@ public:
if (copyOfStr=="sp_taunt") {_Value=SP_TAUNT; return *this;}
if (copyOfStr=="sp_shielding") {_Value=SP_SHIELDING; return *this;}
if (copyOfStr=="sp_life_aura") {_Value=SP_LIFE_AURA; return *this;}
if (copyOfStr=="sp_life_aura2") {_Value=SP_LIFE_AURA2; return *this;}
if (copyOfStr=="sp_stamina_aura") {_Value=SP_STAMINA_AURA; return *this;}
if (copyOfStr=="sp_sap_aura") {_Value=SP_SAP_AURA; return *this;}
if (copyOfStr=="sp_stamina_aura2") {_Value=SP_STAMINA_AURA2; return *this;}
if (copyOfStr=="sp_sap_aura") {_Value=SP_SAP_AURA; return *this;}
if (copyOfStr=="sp_sap_aura2") {_Value=SP_SAP_AURA2; return *this;}
if (copyOfStr=="sp_speeding_up") {_Value=SP_SPEEDING_UP; return *this;}
if (copyOfStr=="sp_invulnerability") {_Value=SP_INVULNERABILITY; return *this;}
if (copyOfStr=="sp_melee_protection_aura") {_Value=SP_MELEE_PROTECTION_AURA; return *this;}
@ -3843,6 +3849,54 @@ struct CSBrickParamLifeAura : public TBrickParam::IId
};
struct CSBrickParamLifeAura2 : public TBrickParam::IId
{
// regen modifier (in %)
uint16 RegenMod;
// duration in seconds
float Duration;
// aura radius in meters
float Radius;
// disable life aura for x seconds on targets
float TargetDisableTime;
// disable life aura for x seconds on user
float UserDisableTime;
CSBrickParamLifeAura2():
RegenMod(),
Duration(),
Radius(),
TargetDisableTime(),
UserDisableTime()
{
_Id = TBrickParam::SP_LIFE_AURA2;
}
CSBrickParamLifeAura2(const std::string&str)
{
*this=CSBrickParamLifeAura2();
*this=str;
}
const CSBrickParamLifeAura2& operator=(const std::string& input)
{
std::vector<std::string> args;
convertInput(args, input);
if (args.size()!=5)
return *this;
ParsedOk=true;
RegenMod=atoi(args[0].c_str());
Duration=(float)atof(args[1].c_str());
Radius=(float)atof(args[2].c_str());
TargetDisableTime=(float)atof(args[3].c_str());
UserDisableTime=(float)atof(args[4].c_str());
return *this;
}
};
struct CSBrickParamStaminaAura : public TBrickParam::IId
{
// regen modifier (in %)
@ -3891,7 +3945,53 @@ struct CSBrickParamStaminaAura : public TBrickParam::IId
}
};
struct CSBrickParamStaminaAura2 : public TBrickParam::IId
{
// regen modifier (in %)
uint16 RegenMod;
// duration in seconds
float Duration;
// aura radius in meters
float Radius;
// disable life aura for x seconds on targets
float TargetDisableTime;
// disable life aura for x seconds on user
float UserDisableTime;
CSBrickParamStaminaAura2():
RegenMod(),
Duration(),
Radius(),
TargetDisableTime(),
UserDisableTime()
{
_Id = TBrickParam::SP_STAMINA_AURA2;
}
CSBrickParamStaminaAura2(const std::string&str)
{
*this=CSBrickParamStaminaAura2();
*this=str;
}
const CSBrickParamStaminaAura2& operator=(const std::string& input)
{
std::vector<std::string> args;
convertInput(args, input);
if (args.size()!=5)
return *this;
ParsedOk=true;
RegenMod=atoi(args[0].c_str());
Duration=(float)atof(args[1].c_str());
Radius=(float)atof(args[2].c_str());
TargetDisableTime=(float)atof(args[3].c_str());
UserDisableTime=(float)atof(args[4].c_str());
return *this;
}
};
struct CSBrickParamSapAura : public TBrickParam::IId
{
// regen modifier (in %)
@ -3940,7 +4040,53 @@ struct CSBrickParamSapAura : public TBrickParam::IId
}
};
struct CSBrickParamSapAura2 : public TBrickParam::IId
{
// regen modifier (in %)
uint16 RegenMod;
// duration in seconds
float Duration;
// aura radius in meters
float Radius;
// disable life aura for x seconds on targets
float TargetDisableTime;
// disable life aura for x seconds on user
float UserDisableTime;
CSBrickParamSapAura2():
RegenMod(),
Duration(),
Radius(),
TargetDisableTime(),
UserDisableTime()
{
_Id = TBrickParam::SP_SAP_AURA2;
}
CSBrickParamSapAura2(const std::string&str)
{
*this=CSBrickParamSapAura2();
*this=str;
}
const CSBrickParamSapAura2& operator=(const std::string& input)
{
std::vector<std::string> args;
convertInput(args, input);
if (args.size()!=5)
return *this;
ParsedOk=true;
RegenMod=atoi(args[0].c_str());
Duration=(float)atof(args[1].c_str());
Radius=(float)atof(args[2].c_str());
TargetDisableTime=(float)atof(args[3].c_str());
UserDisableTime=(float)atof(args[4].c_str());
return *this;
}
};
struct CSBrickParamSpeedingUp : public TBrickParam::IId
{
// speed modifier (in %)

View file

@ -45,6 +45,7 @@ bool CMissionEvent::simMissionEvent(const std::vector< std::string > & script, C
NL_STRING_CONVERSION_TABLE_ENTRY(EnterZone)
NL_STRING_CONVERSION_TABLE_ENTRY(Cast)
NL_STRING_CONVERSION_TABLE_ENTRY(Kill)
NL_STRING_CONVERSION_TABLE_ENTRY(KillPlayer)
NL_STRING_CONVERSION_TABLE_ENTRY(BuyItem)
NL_STRING_CONVERSION_TABLE_ENTRY(SellItem)
NL_STRING_CONVERSION_TABLE_ENTRY(Forage)
@ -93,6 +94,9 @@ bool CMissionEvent::simMissionEvent(const std::vector< std::string > & script, C
case Kill:
event = new CMissionEventKill;
break;
case KillPlayer:
event = new CMissionEventKillPlayer;
break;
case BuyItem:
event = new CMissionEventBuyItem;
break;
@ -266,7 +270,24 @@ bool CMissionEventKill::buildFromScript( const std::vector< std::string > & scri
TargetEntity = c->getEntityRowId();
return true;
}
bool CMissionEventKillPlayer::buildFromScript( const std::vector< std::string > & script ,NLMISC::CLog& log)
{
if ( script.size() != 1 )
{
log.displayNL("param entity expected");
return false;
}
CEntityId id;
id.fromString( script[0].c_str() );
CCharacter *victim = PlayerManager.getChar( id );
if ( !victim )
{
log.displayNL("invalid victim entity %s",script[0].c_str() );
return false;
}
TargetEntity = victim->getEntityRowId();
return true;
}
bool CMissionEventBuyItem::buildFromScript( const std::vector< std::string > & script ,NLMISC::CLog& log)
{
bool ret = true;

View file

@ -50,6 +50,7 @@ public:
EnterZone,
Cast,
Kill,
KillPlayer,
BuyItem,
SellItem,
Forage,
@ -200,6 +201,18 @@ protected:
};
/// "Kill player" event
class CMissionEventKillPlayer : public CMissionEvent
{
public:
CMissionEventKillPlayer(const TDataSetRow & victimId)
:CMissionEvent(KillPlayer, victimId){}
protected:
friend class CMissionEvent;
CMissionEventKillPlayer(){};
bool buildFromScript( const std::vector< std::string > & script ,NLMISC::CLog& log);
};
/// "buy" event
class CMissionEventBuyItem: public CMissionEvent
{

View file

@ -29,6 +29,7 @@
#include "mission_manager/mission_parser.h"
#include "nel/misc/algo.h"
#include "game_share/fame.h"
#include "game_share/pvp_clan.h"
using namespace std;
using namespace NLMISC;
@ -39,6 +40,7 @@ Steps linked with kill events
-kill_fauna
-kill_species ( from the GSPeople::EPeople enum )
-kill_npc
-kill_player
***************************************************************************************************/
// ----------------------------------------------------------------------------
@ -795,7 +797,6 @@ class CMissionStepKillByName : public IMissionStepTemplate
{
if ( event.Type == CMissionEvent::Kill )
{
CMissionStepKillByName & eventSpe = (CMissionStepKillByName&)event;
CCreature * c = CreatureManager.getCreature( event.TargetEntity );
if ( !c )
{
@ -888,3 +889,206 @@ class CMissionStepKillByName : public IMissionStepTemplate
MISSION_STEP_GETNEWPTR(CMissionStepKillByName)
};
MISSION_REGISTER_STEP(CMissionStepKillByName,"kill_npc_by_name");
// ----------------------------------------------------------------------------
class CMissionStepKillPlayer : public IMissionStepTemplate
{
struct CSubStep
{
sint32 Clan;
sint32 MinLevel;
sint32 MaxLevel;
uint16 Quantity;
};
virtual bool buildStep( uint32 line, const std::vector< std::string > & script, CMissionGlobalParsingData & globalData, CMissionSpecificParsingData & missionData )
{
_SourceLine = line;
_Place = 0xFFFF;
if ( script.size() < 2 || script.size() > 3)
{
MISLOGSYNTAXERROR("<clan_name> <min_level> <max_level> <quantity> *[; <clan_name> <min_level> <max_level> <quantity>] [:<place>]");
return false;
}
std::vector< std::string > subs;
NLMISC::splitString( script[1],";", subs );
for ( uint i = 0; i < subs.size(); i++ )
{
std::vector< std::string > args;
CMissionParser::tokenizeString( subs[i]," \t", args );
if ( args.size() != 4 )
{
MISLOGSYNTAXERROR("<clan_name> <min_level> <max_level> <quantity> *[; <clan_name> <min_level> <max_level> <quantity>] [:<place>]");
return false;
}
CSubStep subStep;
subStep.Clan = PVP_CLAN::getFactionIndex(PVP_CLAN::fromString(args[0]));
if ( subStep.Clan == CStaticFames::INVALID_FACTION_INDEX )
{
MISLOGERROR("invalid faction name (Allowed = kami/karavan/tryker/matis/fyros/zorai)");
return false;
}
// missionData.ChatParams.push_back( make_pair( args[0], STRING_MANAGER::clan ) );
subStep.MinLevel = atoi( args[1].c_str() ) * kFameMultipler;
subStep.MaxLevel = atoi( args[2].c_str() ) * kFameMultipler;
if ( subStep.MinLevel >= subStep.MaxLevel )
{
MISLOGERROR("min_level >= max_level");
return false;
}
subStep.Quantity = (uint16) atoi( args[3].c_str() );
if ( subStep.Quantity == 0 )
{
MISLOGERROR("invalid quantity 0");
return false;
}
_SubSteps.push_back( subStep );
}
if ( script.size() == 3 )
{
string placeStr = CMissionParser::getNoBlankString( script[2] );
missionData.ChatParams.push_back( make_pair(placeStr,STRING_MANAGER::place) );
CPlace * place = CZoneManager::getInstance().getPlaceFromName( placeStr );
if ( !place )
{
MISLOGERROR1("invalid place '%s'", script[2].c_str());
return false;
}
else {_Place = place->getId();}
}
return true;
}
uint processEvent( const TDataSetRow & userRow, const CMissionEvent & event,uint subStepIndex,const TDataSetRow & giverRow )
{
if ( event.Type == CMissionEvent::KillPlayer )
{
CCharacter * victim = PlayerManager.getChar( event.TargetEntity );
if ( !victim )
{
LOGMISSIONSTEPERROR("kill_player : invalid victim " + toString(event.TargetEntity.getIndex()));
}
else
{
sint32 victimFame = CFameInterface::getInstance().getFameIndexed(victim->getId(), _SubSteps[subStepIndex].Clan);
if ( (victimFame > _SubSteps[subStepIndex].MinLevel) &&
(victimFame < _SubSteps[subStepIndex].MaxLevel) )
{
if ( _Place != 0xFFFF )
{
float gooDistance;
const CPlace * stable = NULL;
std::vector<const CPlace *> places;
const CRegion * region = NULL;
const CContinent * continent = NULL;
if ( !CZoneManager::getInstance().getPlace( victim->getState().X, victim->getState().Y, gooDistance, &stable, places, &region , &continent ) )
return 0;
if ( continent && continent->getId() == _Place )
{
LOGMISSIONSTEPSUCCESS("kill_player");
return 1;
}
if ( region && region->getId() == _Place )
{
LOGMISSIONSTEPSUCCESS("kill_player");
return 1;
}
for ( uint i = 0; i < places.size(); i++ )
{
if ( places[i] && places[i]->getId() == _Place )
{
LOGMISSIONSTEPSUCCESS("kill_player");
return 1;
}
}
return 0;
}
else
{
LOGMISSIONSTEPSUCCESS("kill_player");
return 1;
}
}
}
}
return 0;
}
void getInitState( std::vector<uint32>& ret )
{
ret.clear();
ret.resize( _SubSteps.size() );
for ( uint i = 0; i < _SubSteps.size(); i++ )
{
ret[i] = _SubSteps[i].Quantity;
}
}
virtual void getTextParams( uint & nbSubSteps, const std::string* & textPtr,TVectorParamCheck& retParams, const std::vector<uint32>& subStepStates)
{
static const std::string stepText = "MIS_KILL_PLAYER";
static const std::string stepTextLoc = "MIS_KILL_PLAYER_LOC";
if ( _Place != 0xFFFF )
retParams.resize(3);
else
retParams.resize(2);
textPtr = &stepText;
nlassert( _SubSteps.size() == subStepStates.size() );
for ( uint i = 0; i < subStepStates.size(); i++ )
{
if( subStepStates[i] != 0 )
{
nbSubSteps++;
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::faction;
retParams.back().Enum = _SubSteps[i].Clan;
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::integer;
retParams.back().Int = _SubSteps[i].MinLevel;
retParams.push_back(STRING_MANAGER::TParam());
retParams.back().Type = STRING_MANAGER::integer;
retParams.back().Int = _SubSteps[i].MaxLevel;
}
}
/*
if ( _Place != 0xFFFF )
{
STRING_MANAGER::TParam param;
param.Type = STRING_MANAGER::place;
CPlace * place = CZoneManager::getInstance().getPlaceFromId(_Place);
if ( !place )
{
MISLOG("sline:%u ERROR : kill_player : Invalid place %u", _SourceLine, _Place);
}
else
{
param.Identifier = place->getName();
retParams.push_back(param);
}
textPtr = &stepTextLoc;
}
else
*/
textPtr = &stepText;
}
std::vector< CSubStep > _SubSteps;
uint16 _Place;
MISSION_STEP_GETNEWPTR(CMissionStepKillPlayer)
};
MISSION_REGISTER_STEP(CMissionStepKillPlayer, "kill_player");

View file

@ -560,7 +560,7 @@ public:
else
{
CPlayer *p = PlayerManager.getPlayer(uint32(character->getId().getShortId())>>4);
if (p && p->havePriv(":SGM:GM:VG:SG:G"))
if (p && p->havePriv(":SGM:GM:VG:SG:G:"))
{
// do not override state with those from the ring
}

View file

@ -135,21 +135,28 @@ void CAuraRootEffect::createEffectOnEntity(CEntityBase *entity, CEntityBase *cre
}
else
{
auraEffect->addLifeTime();
if (_Value < auraEffect->getParamValue())
{
auraEffect->stopEffect();
}
else
{
auraEffect->addLifeTime();
return;
}
}
return;
}
}
// no effect found, create one if the entity can receive this effect
static NLMISC::TGameCycle endDate;
if (character->isAuraEffective(_PowerType, endDate, creator->getId()) )
if (character->isAuraEffective(_PowerType, endDate, creator->getId()) || _IsFromConsumable )
{
CAuraBaseEffect *effect = IAuraEffectFactory::buildEffectFromPowerType(_PowerType, *this, entity->getEntityRowId());
if (effect)
{
effect->setIsFromConsumable(_IsFromConsumable);
effect->setEffectDisabledEndDate( CTickEventHandler::getGameCycle() + _TargetDisableTime );
entity->addSabrinaEffect(effect);
character->useAura(_PowerType, CTickEventHandler::getGameCycle(), CTickEventHandler::getGameCycle() + _TargetDisableTime, creator->getId());
@ -218,6 +225,7 @@ CAuraBaseEffect::CAuraBaseEffect( const CAuraRootEffect &rootEffect, TDataSetRow
CTickEventHandler::getGameCycle() + (NLMISC::TGameCycle)AurasUpdateFrequency.get() + 10)
{
_PowerType = rootEffect.powerType();
_IsFromConsumable = false;
}
void CAuraBaseEffect::addLifeTime()
@ -252,8 +260,10 @@ void CAuraBaseEffect::removed()
if (_EffectIndexInDB >= 0)
{
// player->removeEffectInDB((uint8)_EffectIndexInDB, true);
player->disableEffectInDB( (uint8)_EffectIndexInDB,true, _DisabledEndDate);
if (_IsFromConsumable)
player->removeEffectInDB((uint8)_EffectIndexInDB, true);
else
player->disableEffectInDB( (uint8)_EffectIndexInDB,true, _DisabledEndDate);
}
} // removed //

View file

@ -49,6 +49,7 @@ public:
_PowerType(powerType), _CreatedEffectFamily(effectFamily)
{
_AffectGuild = affectGuild;
_IsFromConsumable = false;
#ifdef NL_DEBUG
_LastUpdateDate = CTickEventHandler::getGameCycle();
#endif
@ -69,6 +70,7 @@ public:
inline void setRadius(float radius) { _AuraRadius = radius; }
// set disable time for targets
inline void setTargetDisableTime(NLMISC::TGameCycle time) { _TargetDisableTime = time; }
inline void setIsFromConsumable(bool fromConsumable) { _IsFromConsumable = fromConsumable; }
protected:
/// create or update the real effect on target entity
@ -93,6 +95,8 @@ private:
// is aura affecting guild members ? (teammates are always affected)
bool _AffectGuild;
bool _IsFromConsumable;
#ifdef NL_DEBUG
NLMISC::TGameCycle _LastUpdateDate;
#endif

View file

@ -1053,6 +1053,11 @@ bool CCombatPhrase::validate()
if ( _Attacker->getItem( CCombatAttacker::RightHandItem, _RightWeapon) )
{
// forbid use of multi target with an area effect weapon !!!!
if ( FightAreaEffectOn && _RightWeapon.Area && _HitAllMeleeAggressors )
return false;
if (_RightWeapon.Family == ITEMFAMILY::MELEE_WEAPON )
{
_MeleeCombat = true;

View file

@ -662,10 +662,19 @@ protected:
for (it=effects.begin(), itEnd=effects.end(); it!=itEnd; ++it)
{
float rnd = RandomGenerator.frand();
if (rnd<it->EffectArgFloat[0])
float effect0 = it->EffectArgFloat[0];
float effect1 = it->EffectArgFloat[1];
// Clamp boost when player do not have required privs
if (!character->havePriv(":DEV:") && !character->havePriv(":SGM:"))
{
applyProcAddLimit(Params, statBitField, it->EffectArgFloat[1]);
PHRASE_UTILITIES::sendItemSpecialEffectProcMessage(ITEM_SPECIAL_EFFECT::ISE_CRAFT_ADD_LIMIT, character, NULL, (sint32)(it->EffectArgFloat[1]*100.f));
clamp(effect0, 0.f, 0.25f);
clamp(effect1, 0.f, 0.25f);
}
if (rnd < effect0)
{
applyProcAddLimit(Params, statBitField, effect1);
PHRASE_UTILITIES::sendItemSpecialEffectProcMessage(ITEM_SPECIAL_EFFECT::ISE_CRAFT_ADD_LIMIT, character, NULL, (sint32)(effect1*100.f));
}
}
}

View file

@ -421,7 +421,7 @@ void CMagicPhrase::computeCastingTime(float castingTimeFactor, float wearMalus)
nlwarning("CMagicPhrase:computeCastingTime: _MaxCastTime(%u) < _MinCastTime(%u)", _MaxCastTime, _MinCastTime);
_MaxCastTime = _MinCastTime;
}
// apply magic focus item factor
float meanFactor = 0.0f;
for (uint i = 0 ; i < _Skills.size() ; ++i)
@ -922,6 +922,9 @@ void CMagicPhrase::execute()
}
castingTime = NLMISC::TGameCycle ( castingTime * (slowingParam / 100.0f + 1.0f ) );
if (_Nature == ACTNATURE::RECHARGE)
castingTime /= 2;
_ExecutionEndDate = time + castingTime;
if (_IsStatic && caster->getId().getType() == RYZOMID::player )
@ -954,6 +957,9 @@ void CMagicPhrase::execute()
case ACTNATURE::OFFENSIVE_MAGIC:
behav = MBEHAV::CAST_OFF;
break;
case ACTNATURE::RECHARGE:
behav = MBEHAV::CAST_MIX;
break;
}
}
else
@ -1412,6 +1418,10 @@ bool CMagicPhrase::launch()
// tmp nico : stats about projectiles
projStatsIncrement();
break;
case ACTNATURE::RECHARGE:
behav = MBEHAV::CAST_MIX_SUCCESS;
break;
}
}
else
@ -1428,6 +1438,10 @@ bool CMagicPhrase::launch()
case ACTNATURE::OFFENSIVE_MAGIC:
behav = MBEHAV::CAST_OFF_FAIL;
break;
case ACTNATURE::RECHARGE:
behav = MBEHAV::CAST_MIX_FAIL;
break;
}
}
}
@ -1769,6 +1783,10 @@ void CMagicPhrase::stop()
case ACTNATURE::OFFENSIVE_MAGIC:
behav = MBEHAV::CAST_OFF_FAIL;
break;
case ACTNATURE::RECHARGE:
behav = MBEHAV::CAST_MIX_FAIL;
break;
}
// set behaviour
PHRASE_UTILITIES::sendUpdateBehaviour( _ActorRowId, behav );

View file

@ -96,7 +96,7 @@ public:
///\ctor
CSEffect()
:_IsRemoved(false),_Value(0),_Power(0)
:_IsRemoved(false),_Value(0),_Power(0),_IsFromConsumable(false)
{
_UpdateTimer.setRemaining(1, new CUpdateEffectTimerEvent(this, true));
_Skill = SKILLS::unknown;
@ -106,7 +106,7 @@ public:
}
inline CSEffect( const TDataSetRow & creatorRowId, const TDataSetRow & targetRowId, EFFECT_FAMILIES::TEffectFamily family, bool stackable, sint32 effectValue, uint32 power)
:_CreatorRowId(creatorRowId),_TargetRowId(targetRowId),_Family(family),_Value(effectValue),_Power(power),_IsStackable(stackable),_IsRemoved(false)
:_CreatorRowId(creatorRowId),_TargetRowId(targetRowId),_Family(family),_Value(effectValue),_Power(power),_IsStackable(stackable),_IsRemoved(false),_IsFromConsumable(false)
{
++NbAllocatedEffects;
_EffectChatName = EFFECT_FAMILIES::getAssociatedChatId(family); // txt msg
@ -160,7 +160,13 @@ public:
inline sint32 getParamValue() const{ return _Value;}
inline uint32 getPower() const{ return _Power;}
inline SKILLS::ESkills getSkill() const{ return _Skill; }
virtual NLMISC::CSheetId getAssociatedSheetId() const { return EFFECT_FAMILIES::getAssociatedSheetId(_Family); }
virtual NLMISC::CSheetId getAssociatedSheetId() const
{
if (_IsFromConsumable)
return NLMISC::CSheetId("hatred.sbrick");
else
return EFFECT_FAMILIES::getAssociatedSheetId(_Family);
}
//@}
///\name write accessors
@ -203,6 +209,10 @@ public:
/// set if the effect has been removed from affected entity
inline void isRemoved(bool removed) { _IsRemoved = removed; }
inline void setIsFromConsumable(bool fromConsumable) { _IsFromConsumable = fromConsumable; }
inline bool getIsFromConsumable() { return _IsFromConsumable; }
protected:
/// send chat message for effect begin
void sendEffectBeginMessages();
@ -245,6 +255,9 @@ protected:
/// timer used to end the effect
CTimer _EndTimer;
bool _IsFromConsumable;
public:
static uint32 NbAllocatedEffects;
static uint32 NbDesallocatedEffects;

View file

@ -49,7 +49,10 @@ bool CSpecialPower::validate(std::string &errorCode)
nlwarning("<CSpecialPower::validate> Cannot find actor entity or not a player");
return false;
}
if (_ByPassDisablePowerTimer)
return true;
TGameCycle endDate;
if (!actor->canUsePower(_PowerType, (uint16)~0, endDate))
{
@ -87,6 +90,8 @@ bool CSpecialPowerAuras::validate(std::string &errorCode)
if (actor->isDead())
return false;
if (_ByPassTargetsDisableAuraTime)
return true;
TGameCycle endDate = actor->getForbidAuraUseEndDate();
if (actor->getForbidAuraUseEndDate() >= CTickEventHandler::getGameCycle())
{

View file

@ -38,7 +38,7 @@ class CSpecialPower
NL_INSTANCE_COUNTER_DECL(CSpecialPower);
public:
/// Constructor
CSpecialPower() : _Phrase(NULL), _ApplyOnTargets(true), _PowerType(POWERS::UnknownType), _DisablePowerTime(0)
CSpecialPower() : _Phrase(NULL), _ApplyOnTargets(true), _PowerType(POWERS::UnknownType), _DisablePowerTime(0), _ByPassDisablePowerTimer(false)
{}
/// validate the power utilisation
@ -51,6 +51,9 @@ public:
inline bool applyOnTargets() const { return _ApplyOnTargets; }
inline void applyOnTargets(bool b) { _ApplyOnTargets = b; }
/// set ByPass DisablePowerTimer
inline void setByPass(bool flag) { _ByPassDisablePowerTimer = flag; }
protected:
/// actor
TDataSetRow _ActorRowId;
@ -66,6 +69,8 @@ protected:
/// related phrase
CSpecialPowerPhrase *_Phrase;
bool _ByPassDisablePowerTimer;
};
/**
@ -83,6 +88,7 @@ public:
_TargetsDisableAuraTime = 0;
_AuraRadius = 0.0f;
_AffectGuild = false;
_ByPassTargetsDisableAuraTime = false;
}
/// validate the power utilisation
@ -96,6 +102,9 @@ public:
/// set affect guild flag
inline void affectGuild(bool flag) { _AffectGuild = flag; }
/// set ByPass TargetsDisableAuraTime
inline void setByPass(bool flag) { _ByPassTargetsDisableAuraTime = flag; }
protected:
// disable this aura on targets for x ticks
@ -104,6 +113,9 @@ protected:
float _AuraRadius;
/// affect guild members ? (always affect teammates)
bool _AffectGuild;
bool _ByPassTargetsDisableAuraTime;
};
#endif // RYZOM_SPECIAL_POWER_H

View file

@ -54,7 +54,10 @@ void CSpecialPowerBasicAura::apply()
}
// disable auras
actor->setForbidAuraUseDates(CTickEventHandler::getGameCycle(), CTickEventHandler::getGameCycle() + _DisablePowerTime);
if (!_ByPassTargetsDisableAuraTime)
{
actor->setForbidAuraUseDates(CTickEventHandler::getGameCycle(), CTickEventHandler::getGameCycle() + _DisablePowerTime);
}
const TGameCycle endDate = _Duration + CTickEventHandler::getGameCycle();
@ -66,7 +69,11 @@ void CSpecialPowerBasicAura::apply()
return;
}
effect->setRadius(_AuraRadius);
effect->setIsFromConsumable(_ByPassTargetsDisableAuraTime);
effect->setTargetDisableTime(_TargetsDisableAuraTime);
actor->addSabrinaEffect(effect);
// add aura FX on the actor

View file

@ -118,7 +118,7 @@ bool CSpecialPowerPhrase::buildFromConsumable(const TDataSetRow & actorRowId, co
//-----------------------------------------------
// CSpecialPowerPhrase processParams
//-----------------------------------------------
void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &params, bool /*isConsumable*/, uint16 quality)
void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &params, bool isConsumable, uint16 quality)
{
// process params
for ( uint j = 0 ; j < params.size() ; ++j)
@ -172,6 +172,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
power->setNoShieldProtection( ((CSBrickParamShielding *)param)->NoShieldProtectionFactor / 100.0f, ((CSBrickParamShielding *)param)->NoShieldProtectionMax);
power->setBucklerProtection( ((CSBrickParamShielding *)param)->BucklerProtectionFactor / 100.0f, ((CSBrickParamShielding *)param)->BucklerProtectionMax);
power->setShieldProtection( ((CSBrickParamShielding *)param)->ShieldProtectionFactor / 100.0f, ((CSBrickParamShielding *)param)->ShieldProtectionMax);
power->setByPass(isConsumable);
_Powers.push_back(power);
}
break;
@ -191,11 +192,32 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
lifeAura->setRadius(((CSBrickParamLifeAura *)param)->Radius);
lifeAura->setFamilies(EFFECT_FAMILIES::PowerRootLifeAura,EFFECT_FAMILIES::PowerLifeAura );
lifeAura->setParamValue(((CSBrickParamLifeAura *)param)->RegenMod);
lifeAura->setByPass(isConsumable);
_Powers.push_back(lifeAura);
}
}
break;
case TBrickParam::SP_LIFE_AURA2:
{
// $*STRUCT CSBrickParamLifeAura: public TBrickParam::CId <TBrickParam::SP_LIFE_AURA2>
// $*-i uint16 RegenMod // regen modifier proportionally to item level
// $*-f float Duration // duration in seconds
// $*-f float Radius // aura radius in meters
// $*-f float TargetDisableTime // disable life aura for x seconds on targets
// $*-f float UserDisableTime // disable life aura for x seconds on user
CSpecialPowerBasicAura *lifeAura = new CSpecialPowerBasicAura(_ActorRowId, this, ((CSBrickParamLifeAura *)param)->Duration, ((CSBrickParamLifeAura *)param)->UserDisableTime, ((CSBrickParamLifeAura *)param)->TargetDisableTime, POWERS::LifeAura);
if (lifeAura)
{
lifeAura->setRadius(((CSBrickParamLifeAura *)param)->Radius);
lifeAura->setFamilies(EFFECT_FAMILIES::PowerRootLifeAura,EFFECT_FAMILIES::PowerLifeAura );
lifeAura->setParamValue(((CSBrickParamLifeAura *)param)->RegenMod*quality);
lifeAura->setByPass(isConsumable);
_Powers.push_back(lifeAura);
}
}
break;
case TBrickParam::SP_STAMINA_AURA:
{
CSpecialPowerBasicAura *staminaAura = new CSpecialPowerBasicAura(_ActorRowId, this, ((CSBrickParamStaminaAura*)param)->Duration, ((CSBrickParamLifeAura *)param)->UserDisableTime, ((CSBrickParamStaminaAura *)param)->TargetDisableTime, POWERS::StaminaAura);
@ -204,11 +226,26 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
staminaAura->setRadius(((CSBrickParamStaminaAura *)param)->Radius);
staminaAura->setFamilies(EFFECT_FAMILIES::PowerRootStaminaAura,EFFECT_FAMILIES::PowerStaminaAura );
staminaAura->setParamValue(((CSBrickParamStaminaAura *)param)->RegenMod);
staminaAura->setByPass(isConsumable);
_Powers.push_back(staminaAura);
}
}
break;
case TBrickParam::SP_STAMINA_AURA2:
{
CSpecialPowerBasicAura *staminaAura = new CSpecialPowerBasicAura(_ActorRowId, this, ((CSBrickParamStaminaAura*)param)->Duration, ((CSBrickParamLifeAura *)param)->UserDisableTime, ((CSBrickParamStaminaAura *)param)->TargetDisableTime, POWERS::StaminaAura);
if (staminaAura)
{
staminaAura->setRadius(((CSBrickParamStaminaAura *)param)->Radius);
staminaAura->setFamilies(EFFECT_FAMILIES::PowerRootStaminaAura,EFFECT_FAMILIES::PowerStaminaAura );
staminaAura->setParamValue(((CSBrickParamStaminaAura *)param)->RegenMod*quality);
staminaAura->setByPass(isConsumable);
_Powers.push_back(staminaAura);
}
}
break;
case TBrickParam::SP_SAP_AURA:
{
CSpecialPowerBasicAura *sapAura = new CSpecialPowerBasicAura(_ActorRowId, this, ((CSBrickParamSapAura*)param)->Duration, ((CSBrickParamLifeAura *)param)->UserDisableTime, ((CSBrickParamSapAura *)param)->TargetDisableTime, POWERS::SapAura);
@ -217,11 +254,25 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
sapAura->setRadius(((CSBrickParamSapAura *)param)->Radius);
sapAura->setFamilies(EFFECT_FAMILIES::PowerRootSapAura,EFFECT_FAMILIES::PowerSapAura );
sapAura->setParamValue(((CSBrickParamSapAura *)param)->RegenMod);
sapAura->setByPass(isConsumable);
_Powers.push_back(sapAura);
}
}
break;
case TBrickParam::SP_SAP_AURA2:
{
CSpecialPowerBasicAura *sapAura = new CSpecialPowerBasicAura(_ActorRowId, this, ((CSBrickParamSapAura*)param)->Duration, ((CSBrickParamLifeAura *)param)->UserDisableTime, ((CSBrickParamSapAura *)param)->TargetDisableTime, POWERS::SapAura);
if (sapAura)
{
sapAura->setRadius(((CSBrickParamSapAura *)param)->Radius);
sapAura->setFamilies(EFFECT_FAMILIES::PowerRootSapAura,EFFECT_FAMILIES::PowerSapAura );
sapAura->setParamValue(((CSBrickParamSapAura *)param)->RegenMod*quality);
sapAura->setByPass(isConsumable);
_Powers.push_back(sapAura);
}
}
break;
case TBrickParam::SP_SPEEDING_UP:
{
@ -232,6 +283,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
CSpecialPowerSpeedingUp *power = new CSpecialPowerSpeedingUp(_ActorRowId, this, (uint8)((CSBrickParamSpeedingUp *)param)->SpeedMod, ((CSBrickParamSpeedingUp *)param)->Duration, ((CSBrickParamSpeedingUp *)param)->DisableTime);
if (power)
{
power->setByPass(isConsumable);
_Powers.push_back(power);
}
}
@ -246,6 +298,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
if (power)
{
power->setEffectFamily( EFFECT_FAMILIES::PowerInvulnerability );
power->setByPass(isConsumable);
_Powers.push_back(power);
}
}
@ -263,6 +316,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
{
aura->setRadius(((CSBrickParamMeleeProtection *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootProtection,EFFECT_FAMILIES::PowerProtection );
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
}
@ -280,6 +334,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
{
aura->setRadius(((CSBrickParamRangeProtection *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootUmbrella,EFFECT_FAMILIES::PowerUmbrella);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
}
@ -297,6 +352,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
{
aura->setRadius(((CSBrickParamMagicProtection *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootAntiMagicShield,EFFECT_FAMILIES::PowerAntiMagicShield);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
}
@ -316,6 +372,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
aura->setParamValue(((CSBrickParamWarCry *)param)->DamageBonus);
aura->setRadius(((CSBrickParamWarCry *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootWarCry,EFFECT_FAMILIES::PowerWarCry);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
break;
@ -335,6 +392,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
aura->setParamValue(((CSBrickParamFireWall *)param)->Damage);
aura->setRadius(((CSBrickParamFireWall *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootFireWall,EFFECT_FAMILIES::PowerFireWall);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
break;
@ -354,6 +412,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
aura->setParamValue(((CSBrickParamThornWall *)param)->Damage);
aura->setRadius(((CSBrickParamThornWall *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootThornWall,EFFECT_FAMILIES::PowerThornWall);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
break;
@ -373,6 +432,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
aura->setParamValue(((CSBrickParamWaterWall *)param)->Damage);
aura->setRadius(((CSBrickParamWaterWall *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootWaterWall,EFFECT_FAMILIES::PowerWaterWall);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
break;
@ -392,6 +452,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
aura->setParamValue(((CSBrickParamLightningWall *)param)->Damage);
aura->setRadius(((CSBrickParamLightningWall *)param)->Radius);
aura->setFamilies(EFFECT_FAMILIES::PowerRootLightningWall,EFFECT_FAMILIES::PowerLightningWall);
aura->setByPass(isConsumable);
_Powers.push_back(aura);
}
break;
@ -412,6 +473,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
power->setDamagePerUpdate(((CSBrickParamBerserk *)param)->DamagePerUpdate);
power->setParamValue(((CSBrickParamBerserk *)param)->DamageBonus);
power->setEffectFamily( EFFECT_FAMILIES::PowerBerserker );
power->setByPass(isConsumable);
_Powers.push_back(power);
}
}
@ -449,6 +511,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
if (power)
{
power->setAffectedScore( SCORES::toScore(cp->AffectedScore) );
power->setByPass(isConsumable);
_Powers.push_back(power);
}
}
@ -469,6 +532,7 @@ void CSpecialPowerPhrase::processParams(const vector<TBrickParam::IIdPtr> &param
if (power)
{
power->setAffectedScore( SCORES::toScore(cp->AffectedScore) );
power->setByPass(isConsumable);
_Powers.push_back(power);
}
}

View file

@ -34,6 +34,8 @@
//
#include "nel/net/message.h"
#include "game_share/visual_fx.h"
using namespace std;
using namespace NLMISC;
using namespace NLNET;
@ -187,6 +189,15 @@ CGameItemPtr CTPTimedAction::getAndUnlockTP(CEntityBase *actor)
// unlock item, Tp player and destroy item
character->unLockItem(INVENTORIES::bag, ticketSlot,1);
// Remove fx
CMirrorPropValue<TYPE_VISUAL_FX> visualFx( TheDataset, character->getEntityRowId(), DSPropertyVISUAL_FX );
CVisualFX fx;
fx.unpack(visualFx.getValue());
fx.Aura = MAGICFX::NoAura;
sint64 prop;
fx.pack(prop);
visualFx = (sint16)prop;
return item;
}

View file

@ -25,6 +25,8 @@
#include "nel/misc/o_xml.h"
#include "nel/misc/i_xml.h"
#include "nel/misc/path.h"
#include "nel/misc/md5.h"
#include "nel/misc/sha1.h"
#include "nel/misc/vectord.h"
#include "nel/misc/vector_2d.h"
#include "nel/misc/sstring.h"
@ -217,6 +219,7 @@ CVariable<uint32> NBLoginStats("egs","NBLoginStats", "Nb logins stats kept (logo
// Max Bonus/malus/consumable effects displayed by client (database corresponding array must have the same size, and client must process the same size)
const uint32 MaxBonusMalusDisplayed = 12;
const string randomStrings = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#";
// We use this constant instead of the _StartingCharacteristicValues because _StartingCharacteristicValues is not working
//TODO
//const uint32 StartCharacteristicsValue = 10;
@ -4206,6 +4209,20 @@ void CCharacter::setName(const ucstring &name)
}
}
//-----------------------------------------------
// CCharacter::haveBrick check if player have the brick
//-----------------------------------------------
bool CCharacter::haveBrick( const CSheetId& brickId )
{
const CStaticBrick* brickForm = CSheets::getSBrickForm( brickId );
if( brickForm )
{
// if brick already known, just return
if ( _KnownBricks.find( brickId ) != _KnownBricks.end())
return true;
}
return false;
}
//-----------------------------------------------
// CCharacter::addKnownBrick add a know brick
@ -13329,6 +13346,144 @@ uint16 CCharacter::getFirstFreeSlotInKnownPhrase()
} // getFirstFreeSlotInKnownPhrase //
void CCharacter::sendUrl(const string &url, const string &salt)
{
string control;
if (!salt.empty())
{
string checksum = salt+url;
control = "&hmac="+getHMacSHA1((uint8*)&url[0], url.size(), (uint8*)&salt[0], salt.size()).toString();;
}
nlinfo(url.c_str());
TVectorParamCheck titleParams;
TVectorParamCheck textParams;
uint32 userId = PlayerManager.getPlayerId(getId());
std::string name = "CUSTOM_URL_"+toString(userId);
ucstring phrase = ucstring(name+"(){[WEB : "+url+control+"]}");
NLNET::CMessage msgout("SET_PHRASE");
msgout.serial(name);
msgout.serial(phrase);
sendMessageViaMirror("IOS", msgout);
uint32 titleId = STRING_MANAGER::sendStringToUser(userId, "web_transactions", titleParams);
uint32 textId = STRING_MANAGER::sendStringToUser(userId, name, textParams);
PlayerManager.sendImpulseToClient(getId(), "USER:POPUP", titleId, textId);
}
void CCharacter::addWebCommandCheck(const string &url, const string &data, const string &salt)
{
uint webCommand = getWebCommandCheck(url);
string randomString;
for (uint8 i = 0; i < 8; i++)
{
uint32 r = (uint32)((double)rand()/((double)RAND_MAX)*62);
randomString += randomStrings[r];
}
if (webCommand == INVENTORIES::NbBagSlots)
{
CGameItemPtr item = createItemInInventoryFreeSlot(INVENTORIES::bag, 1, 1, CSheetId("web_transaction.sitem"));
if (item != 0)
{
if (data.empty())
{
item->setCustomText(ucstring(url));
vector<string> infos;
NLMISC::splitString(url, "\n", infos);
sendUrl(infos[0]+"&player_eid="+getId().toString()+"&event=command_added", salt);
}
else
{
vector<string> infos;
NLMISC::splitString(data, ",", infos);
string finalData = randomString+infos[0];
for (uint i = 1; i < infos.size(); i++)
{
finalData += ","+randomString+infos[i];
}
item->setCustomText(ucstring(url+"\n"+finalData));
sendUrl(url+"&player_eid="+getId().toString()+"&event=command_added&transaction_id="+randomString, salt);
}
}
}
else
{
CInventoryPtr inv = getInventory(INVENTORIES::bag);
if(inv)
{
CGameItemPtr item = inv->getItem(webCommand);
if (item != NULL && item->getStaticForm() != NULL )
{
if(item->getStaticForm()->Name == "Web Transaction"
|| item->getStaticForm()->Family == ITEMFAMILY::SCROLL)
{
string cText = item->getCustomText().toString();
if (!cText.empty())
{
vector<string> infos;
NLMISC::splitString(cText, "\n", infos);
vector<string> datas;
NLMISC::splitString(infos[1], ",", datas);
sendUrl(infos[0]+"&player_eid="+getId().toString()+"&event=command_added&transaction_id="+datas[0].substr(0, 8), salt);
}
}
}
}
}
}
uint CCharacter::getWebCommandCheck(const string &url)
{
CInventoryPtr inv = getInventory(INVENTORIES::bag);
if(inv)
{
for(uint i = 0; i < INVENTORIES::NbBagSlots; ++i)
{
CGameItemPtr item = inv->getItem(i);
if (item != NULL && item->getStaticForm() != NULL )
{
if(item->getStaticForm()->Name == "Web Transaction"
|| item->getStaticForm()->Family == ITEMFAMILY::SCROLL)
{
string cText = item->getCustomText().toString();
if (!cText.empty())
{
vector<string> infos;
NLMISC::splitString(cText, "\n", infos);
if (infos.size() == 2)
{
if (infos[0] == url)
{
return i;
}
}
}
}
}
}
}
return INVENTORIES::NbBagSlots;
}
uint CCharacter::checkWebCommand(const string &url, const string &data, const string &hmac, const string &salt)
{
if (salt.empty())
return INVENTORIES::NbBagSlots;
uint slot = getWebCommandCheck(url);
if (slot == INVENTORIES::NbBagSlots)
return slot;
string checksum = url + data + getId().toString();
string realhmac = getHMacSHA1((uint8*)&checksum[0], checksum.size(), (uint8*)&salt[0], salt.size()).toString();
if (realhmac == hmac)
return slot;
return INVENTORIES::NbBagSlots;
}
//-----------------------------------------------
// getAvailablePhrasesList
//-----------------------------------------------
@ -13726,9 +13881,12 @@ void CCharacter::setFameValuePlayer(uint32 factionIndex, sint32 playerFame, sint
{
sint32 fame = CFameInterface::getInstance().getFameIndexed(_Id, fameIdx);
if (fame >= PVPFameRequired*6000) {
if (fame >= PVPFameRequired*6000)
{
canPvp = true;
} else if (fame <= -PVPFameRequired*6000) {
}
else if (fame <= -PVPFameRequired*6000)
{
canPvp = true;
}
}
@ -14576,7 +14734,7 @@ void CCharacter::addPlayerToIgnoreList(const NLMISC::CEntityId &id)
// update ios state
uint32 playerId = PlayerManager.getPlayerId(id);
CPlayer *player = PlayerManager.getPlayer( playerId );
if ( (!player) || (!player->havePriv( ":SGM:GM:VG:SG:G:" )) ) // if online, messages from CSRs can't be ignored
if ( (!player) || (!player->havePriv( ":SGM:GM:VG:SG:G:EM:EG:" )) ) // if online, messages from CSRs can't be ignored
{
CEntityId senderId = getId();
CEntityId ignoredId = id;
@ -15078,7 +15236,7 @@ void CCharacter::online(bool onlineStatus)
// if the character has a CSR grade, remove from all ignore lists
if ( onlineStatus && (! _IsIgnoredBy.empty()) && havePriv( ":SGM:GM:VG:SG:G:" ) )
if ( onlineStatus && (! _IsIgnoredBy.empty()) && havePriv( ":SGM:GM:VG:SG:G:EM:EG:" ) )
{
CMessage msgout( "UNIGNORE_ALL" );
msgout.serial( _Id );
@ -15267,6 +15425,8 @@ void CCharacter::onConnection()
{
IShardUnifierEvent::getInstance()->charConnected(_Id, getLastDisconnectionDate());
}
CPVPManager2::getInstance()->playerConnects(this);
}
//--------------------------------------------------------------

View file

@ -702,6 +702,9 @@ public:
/// add a known brick
void addKnownBrick( const NLMISC::CSheetId& brickId );
/// check if have brick
bool haveBrick( const NLMISC::CSheetId& brickId );
/// remove a known brick
void removeKnownBrick( const NLMISC::CSheetId& brickId );
@ -1608,6 +1611,18 @@ public:
/// get ammo item
virtual CGameItemPtr getAmmoItem() const;
/// send custom url
void sendUrl(const std::string &url, const std::string &salt);
/// add web command validation check
void addWebCommandCheck(const std::string &url, const std::string &data, const std::string &salt);
/// get web command validation check
uint getWebCommandCheck(const std::string &url);
/// validate web command. Return web command item index in bag if command is valid or INVENTORIES::NbBagSlots if not
uint checkWebCommand(const std::string &url, const std::string &data, const std::string &hmac, const std::string &salt);
/// get the available phrases
void getAvailablePhrasesList(const std::string &brickFilter, std::vector<NLMISC::CSheetId> &selectedPhrases, EGSPD::CPeople::TPeople people = EGSPD::CPeople::Common, bool bypassBrickRequirements = false, bool includeNonRolemasterBricks = true );
@ -1833,7 +1848,6 @@ public:
void setLastPosXInDB(sint32 x);
/// set last Y pos in DB (for teammates)
void setLastPosYInDB(sint32 y);
/// \name Friend/Ignore lists management.
@ -3410,6 +3424,8 @@ private:
// duel opponent
CCharacter * _DuelOpponent;
TAIAlias _LastCreatedNpcGroup;
// :KLUDGE: ICDBStructNode non-const 'coz getName and getParent are not
// const methods. See CCDBSynchronised::getICDBStructNodeFromName for more
// info.

View file

@ -72,6 +72,9 @@
#include "server_share/log_item_gen.h"
#include "egs_dynamic_sheet_manager.h"
#include "game_share/visual_fx.h"
#include "game_share/teleport_types.h"
///////////
// USING //
///////////
@ -2439,7 +2442,22 @@ void CCharacter::sendItemInfos( uint16 slotId )
infos.TypeSkillMods = item->getTypeSkillMods();
infos.CustomText = item->getCustomText();
// Special case of web missions items
if (item->getStaticForm()->Name == "Web Transaction" || item->getStaticForm()->Family == ITEMFAMILY::SCROLL)
{
string cText = item->getCustomText().toString();
string::size_type sPos = cText.find(" ");
string::size_type ePos = cText.find("\n---\n");
if (sPos != string::npos && sPos != (cText.length()-1) && ePos != string::npos && ePos != (cText.length()-1))
{
string cUrl = cText.substr(sPos, ePos-sPos);
infos.CustomText = ucstring("@WEBIG "+cUrl);
}
else
infos.CustomText = "";
}
else
infos.CustomText = item->getCustomText();
CMessage msgout( "IMPULSION_ID" );
CBitMemStream bms;
@ -2522,11 +2540,10 @@ void CCharacter::createCrystallizedActionItem(const std::vector<NLMISC::CSheetId
// ****************************************************************************
void CCharacter::createRechargeItem(uint32 sapRecharge)
{
static const CSheetId rechargeSheetId("item_sap_recharge.sitem");
if (!EnchantSystemEnabled)
return;
/*** OLD METHOD **********************************************
if (!enterTempInventoryMode(TEMP_INV_MODE::Crystallize))
return;
@ -2535,7 +2552,42 @@ void CCharacter::createRechargeItem(uint32 sapRecharge)
{
item->setSapLoad(sapRecharge);
addItemToInventory(INVENTORIES::temporary, item);
}******/
CInventoryPtr handlingInv = getInventory(INVENTORIES::handling);
if (handlingInv == NULL)
return;
CGameItemPtr rightHandItem = handlingInv->getItem(INVENTORIES::right); // item to reload
if (rightHandItem == NULL)
{
TVectorParamCheck params;
sendDynamicSystemMessage(_EntityRowId, "RIGHT_HAND_EMPTY", params);
return;
}
// check the right hand holds a weapon item
const CStaticItem * form = rightHandItem->getStaticForm();
if (form == NULL)
{
nlwarning("item %s has no static form", rightHandItem->getSheetId().toString().c_str());
return;
}
if ((form->Family != ITEMFAMILY::MELEE_WEAPON) && (form->Family != ITEMFAMILY::RANGE_WEAPON))
{
TVectorParamCheck params;
sendDynamicSystemMessage(_EntityRowId, "WEAPONS_ONLY_CAN_BEEN_RECHARGED", params);
return;
}
rightHandItem->reloadSapLoad(sapRecharge);
SM_STATIC_PARAMS_3(params, STRING_MANAGER::item, STRING_MANAGER::integer, STRING_MANAGER::integer);
params[0].SheetId = rightHandItem->getSheetId();
params[1].Int = rightHandItem->sapLoad();
params[2].Int = rightHandItem->maxSapLoad();
sendDynamicSystemMessage(_EntityRowId, "ITEM_IS_RECHARGED", params);
}
// check if enchant or recharge an item
@ -2858,6 +2910,14 @@ void CCharacter::useItem(uint32 slot)
if ( form->Family == ITEMFAMILY::TELEPORT )
{
pair<PVP_CLAN::TPVPClan, PVP_CLAN::TPVPClan> allegeance = getAllegiance();
if ((form->TpType == TELEPORT_TYPES::KAMI) && (allegeance.first == PVP_CLAN::Karavan)
|| (form->TpType == TELEPORT_TYPES::KARAVAN) && (allegeance.first == PVP_CLAN::Kami))
{
CCharacter::sendDynamicSystemMessage(_Id, "ALTAR_RESTRICTION");
return;
}
if( CPVPManager2::getInstance()->isTPValid(this, item) && IsRingShard == false )
{
// teleport dont work in the same way if the user is dead or alive
@ -2892,6 +2952,35 @@ void CCharacter::useItem(uint32 slot)
_TpTicketSlot = slot;
lockItem( INVENTORIES::bag, slot, 1 );
// add fx
CMirrorPropValue<TYPE_VISUAL_FX> visualFx( TheDataset, _EntityRowId, DSPropertyVISUAL_FX );
CVisualFX fx;
fx.unpack(visualFx.getValue());
if (allegeance.first != PVP_CLAN::None
&& allegeance.first != PVP_CLAN::Neutral
&& CFameInterface::getInstance().getFameIndexed(_Id, PVP_CLAN::getFactionIndex(allegeance.first)) >= 600000)
{
if (allegeance.first == PVP_CLAN::Kami)
{
fx.Aura = MAGICFX::TeleportKami;
}
else if (allegeance.first == PVP_CLAN::Karavan)
{
fx.Aura = MAGICFX::TeleportKara;
}
else
{
fx.Aura = MAGICFX::NoAura;
}
}
else
{
fx.Aura = MAGICFX::NoAura;
}
sint64 prop;
fx.pack(prop);
visualFx = (sint16)prop;
// add tp phrase in manager
static CSheetId tpBrick("bapa01.sbrick");
vector<CSheetId> bricks;
@ -2964,6 +3053,13 @@ void CCharacter::useTeleport(const CStaticItem & form)
}
else
{
CMirrorPropValue<TYPE_VISUAL_FX> visualFx( TheDataset, _EntityRowId, DSPropertyVISUAL_FX );
CVisualFX fx;
fx.unpack(visualFx.getValue());
fx.Aura = MAGICFX::NoAura;
sint64 prop;
fx.pack(prop);
visualFx = (sint16)prop;
sint32 x,y,z;
float theta;
zone->getRandomPoint( x,y,z,theta );

View file

@ -2251,7 +2251,7 @@ bool CPlayerManager::hasBetterCSRGrade( CPlayer* p1, CPlayer *p2, bool devIsNorm
if ( p2->havePriv(":SGM:") )
return ( p1->havePriv(":SGM:") );
if ( p2->havePriv(":EM:") )
return ( p1->havePriv(":SGM:EM:") );
return ( p1->havePriv(":SGM:EM:GM:") );
if ( p2->havePriv(":GM:") )
return ( p1->havePriv(":SGM:EM:GM:") );
if ( p2->havePriv(":EG:") )

View file

@ -401,12 +401,12 @@ void CCharacterProgressionPVE::creatureDeath(TDataSetRow creature)
else
{
const TDataSetRow rowId = TheDataset.getDataSetRow(creatureTakenDmg.PlayerInflictedDamage[index].PlayerId);
creaturePtr->enableLootRights(rowId);
TCharacterActionsContainer::iterator it = _CharacterActions.find(rowId);
if( it != _CharacterActions.end() )
{
// Enable loot rights for this player alone
creaturePtr->enableLootRights(rowId);
// Display XP gain
list<CEntityId> teamMembers;
@ -1528,6 +1528,39 @@ void CCharacterProgressionPVE::enableXpGainForPlayer(const CEntityId &playerId,
}
}
//----------------------------------------------------------------------------
// CCharacterProgressionPVE::removeCreature
//----------------------------------------------------------------------------
void CCharacterProgressionPVE::removeXpCreature(TDataSetRow creature)
{
TCreatureTakenDamageContainer::iterator itCreatureDamage = _CreatureTakenDamage.find(creature);
if (itCreatureDamage == _CreatureTakenDamage.end())
return;
// clear damage inflicted by players and teams on this creature
const vector<CTeamDamage> &damage = (*itCreatureDamage).second.PlayerInflictedDamage;
for (uint i = 0 ; i < damage.size() ; ++i )
{
if (damage[i].TeamId != CTEAM::InvalidTeamId)
{
// forget Xp gain on this creature for whole team
CTeam *team = TeamManager.getRealTeam(damage[i].TeamId);
if (team)
{
const list<CEntityId> &teamMembers = team->getTeamMembers();
for ( list<CEntityId>::const_iterator it = teamMembers.begin() ; it != teamMembers.end() ; ++it)
{
forgetXpGain(creature, TheDataset.getDataSetRow(*it));
}
}
}
else
{
// forget Xp gain on this creature
forgetXpGain(creature, TheDataset.getDataSetRow(damage[i].PlayerId));
}
}
}
//----------------------------------------------------------------------------
// CCharacterProgressionPVE::removeCreature

View file

@ -272,13 +272,14 @@ struct CCreatureTakenDamage
/// return index of the team which has inflicted the most damage, returns -1 if most damage have been made by other creatures
sint16 getMaxInflictedDamageTeamIndex()
{
float maxDmg = TotalCreatureInflictedDamage;
float maxDmg = 0;//TotalCreatureInflictedDamage;
sint16 index = -1;
const uint size = (uint)PlayerInflictedDamage.size();
for ( uint i = 0 ; i < size ; ++i)
{
if ( PlayerInflictedDamage[i].TotalDamage > maxDmg )
{
nlinfo("set damage by player");
maxDmg = PlayerInflictedDamage[i].TotalDamage;
index = (sint16)i;
}
@ -450,6 +451,8 @@ public:
void addDamage(const NLMISC::CEntityId &actorId, const NLMISC::CEntityId &targetId, uint32 damage);
/// enable Xp Gain for a player, set a list with all creatures on which he now has possible Xp Gain
void enableXpGainForPlayer(const NLMISC::CEntityId &playerId, uint16 skillValue, std::list<TDataSetRow> &enabledCreatures);
/// remove xp from a creature (so clear all references on it)
void removeXpCreature(TDataSetRow creature);
/// remove a creature (so clear all references on it)
void removeCreature(TDataSetRow creature);
/// apply regen of a creature

View file

@ -827,6 +827,9 @@ void CRewardedKills::addRewardedKill(NLMISC::CEntityId victimId, const std::vect
for (uint i = 0; i < killers.size(); i++)
{
addRewardedKiller(CRewardedKiller(killers[i], currentDate), rewardedKillers);
CCharacter *killer = PlayerManager.getChar(killers[i]);
CMissionEventKillPlayer killevent( TheDataset.getDataSetRow(victimId) );
killer->processMissionEvent( killevent );
}
}

View file

@ -344,6 +344,42 @@ void CPVPManager2::updateFactionChannel(CCharacter * user, bool b )
*/
}
void CPVPManager2::broadcastMessage(TChanID channel, const ucstring& speakerName, const ucstring& txt)
{
CMessage msgout("DYN_CHAT:SERVICE_CHAT");
msgout.serial(channel);
msgout.serial(const_cast<ucstring&>(speakerName));
msgout.serial(const_cast<ucstring&>(txt));
sendMessageViaMirror("IOS", msgout);
}
void CPVPManager2::sendChannelUsers(TChanID channel, CCharacter * user)
{
std::vector<NLMISC::CEntityId> lst;
TChannelsCharacter::iterator it = _UserChannelCharacters.find(channel);
if(it != _UserChannelCharacters.end())
{
lst = (*it).second;
string players = "";
for (uint i = 0; i < lst.size(); i++)
{
players += "\n"+CEntityIdTranslator::getInstance()->getByEntity(lst[i]).toString();
}
CMessage msgout("DYN_CHAT:SERVICE_TELL");
msgout.serial(channel);
ucstring users = ucstring("<USERS>");
msgout.serial(const_cast<ucstring&>(users));
TDataSetRow senderRow = TheDataset.getDataSetRow(user->getId());
msgout.serial(senderRow);
ucstring txt = ucstring(players);
msgout.serial(const_cast<ucstring&>(txt));
sendMessageViaMirror( "IOS", msgout);
}
}
//----------------------------------------------------------------------------
void CPVPManager2::addFactionChannelToCharacter(TChanID channel, CCharacter * user, bool writeRight, bool userChannel)
{
@ -361,6 +397,23 @@ void CPVPManager2::addFactionChannelToCharacter(TChanID channel, CCharacter * us
currentChannels.push_back(channel);
_CharacterUserChannels.erase(user->getId());
_CharacterUserChannels.insert( make_pair(user->getId(), currentChannels) );
TChannelsCharacter::iterator it = _UserChannelCharacters.find(channel);
if (it == _UserChannelCharacters.end())
{
std::vector<NLMISC::CEntityId> vect;
vect.push_back(user->getId());
_UserChannelCharacters[channel] = vect;
}
else
{
(*it).second.push_back(user->getId());
}
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(user->getId()).toString();
broadcastMessage(channel, string("<INFO>"), "<-- "+playerName);
sendChannelUsers(channel, user);
}
}
}
@ -369,22 +422,40 @@ void CPVPManager2::addFactionChannelToCharacter(TChanID channel, CCharacter * us
//----------------------------------------------------------------------------
void CPVPManager2::removeFactionChannelForCharacter(TChanID channel, CCharacter * user, bool userChannel)
{
std::vector<TChanID> currentChannels = getCharacterRegisteredChannels(user);
std::vector<TChanID> currentChannels;
if (channel == DYN_CHAT_INVALID_CHAN) // Send leaves message to all user channels
{
currentChannels = getCharacterUserChannels(user);
for (uint i = 0; i < currentChannels.size(); i++)
{
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(user->getId()).toString();
broadcastMessage(currentChannels[i], string("<INFO>"), playerName+" -->[]");
}
}
if (userChannel)
{
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(user->getId()).toString();
broadcastMessage(channel, string("<INFO>"), playerName+" -->[]");
}
currentChannels = getCharacterRegisteredChannels(user);
for (uint i = 0; i < currentChannels.size(); i++)
{
if (currentChannels[i] == channel)
if ((currentChannels[i] == channel))
{
DynChatEGS.removeSession(channel, user->getEntityRowId());
if (userChannel && (DynChatEGS.getSessionCount(channel) == 0))
DynChatEGS.removeSession(currentChannels[i], user->getEntityRowId());
if (userChannel && (DynChatEGS.getSessionCount(currentChannels[i]) == 0))
{
DynChatEGS.removeChan(channel);
TMAPPassChannel::iterator it = _PassChannels.find(channel);
DynChatEGS.removeChan(currentChannels[i]);
TMAPPassChannel::iterator it = _PassChannels.find(currentChannels[i]);
if (it != _PassChannels.end())
_PassChannels.erase(it);
for (TMAPExtraFactionChannel::iterator it2 = _UserChannel.begin(); it2 != _UserChannel.end(); ++it2)
{
if ((*it2).second == channel)
if ((*it2).second == currentChannels[i])
_UserChannel.erase(it2);
}
}
@ -416,6 +487,14 @@ void CPVPManager2::removeFactionChannelForCharacter(TChanID channel, CCharacter
_CharacterUserChannels.insert(make_pair(user->getId(), currentChannels));
}
}
TChannelsCharacter::iterator cit = _UserChannelCharacters.find(channel);
if (cit != _UserChannelCharacters.end())
{
std::vector<NLMISC::CEntityId> lst = _UserChannelCharacters[channel];
lst.erase(find(lst.begin(), lst.end(), user->getId()));
_UserChannelCharacters[channel] = lst;
}
}
}
}
@ -437,6 +516,17 @@ void CPVPManager2::addRemoveFactionChannelToUserWithPriviledge(TChanID channel,
}
//----------------------------------------------------------------------------
void CPVPManager2::playerConnects(CCharacter * user)
{
std::vector<TChanID> currentChannels = getCharacterUserChannels(user);
for (uint i = 0; i < currentChannels.size(); i++)
{
const string playerName = CEntityIdTranslator::getInstance()->getByEntity(user->getId()).toString();
broadcastMessage(currentChannels[i], string("<INFO>"), "<-- "+playerName);
}
}
//----------------------------------------------------------------------------
void CPVPManager2::playerDisconnects(CCharacter * user)
{

View file

@ -88,12 +88,18 @@ public:
std::vector<TChanID> getCharacterRegisteredChannels(CCharacter * user);
/// return dynamic user channel TChanId subscribed by character, DYN_CHAT_INVALID_CHAN if character have no user channel
std::vector<TChanID> getCharacterUserChannels(CCharacter * user);
// brodcast message to channel
void broadcastMessage(TChanID channel, const ucstring& speakerName ,const ucstring& txt);
// send list of users to player
void sendChannelUsers(TChanID channel, CCharacter * user);
// add faction channel to character if needed
void addFactionChannelToCharacter(TChanID channel, CCharacter * user, bool writeRight = true, bool userChannel = false);
// remove faction channel for character
void removeFactionChannelForCharacter(TChanID channel, CCharacter * user, bool userChannel = false);
// add/remove faction channel to this character with privilege
void addRemoveFactionChannelToUserWithPriviledge(TChanID channel, CCharacter * user, bool s = true );
/// handle player connection
void playerConnects(CCharacter * user);
/// handle player disconnection
void playerDisconnects(CCharacter * user);
/// handle to add or remove faction channel to player of needed
@ -201,6 +207,8 @@ private:
TMAPFactionChannel _FactionChannel;
TMAPExtraFactionChannel _ExtraFactionChannel;
TMAPExtraFactionChannel _UserChannel;
typedef std::map< TChanID, std::vector<NLMISC::CEntityId> > TChannelsCharacter;
TChannelsCharacter _UserChannelCharacters;
TMAPPassChannel _PassChannels;
/// character registered channel
typedef std::map< NLMISC::CEntityId, std::vector<TChanID> > TCharacterChannels;