Changed: Changes from next patch

This commit is contained in:
kervala 2011-03-03 19:32:52 +01:00
parent 5d0be05baf
commit de93a45ed7
16 changed files with 283 additions and 24 deletions

View file

@ -4284,11 +4284,11 @@ NLMISC_COMMAND (connectUserChannel, "Connect to user channels", "<user id> <chan
CPVPManager2 *inst = CPVPManager2::getInstance();
string pass;
string name = NLMISC::toLower(args[1]);
string name = args[1];
TChanID channel = CPVPManager2::getInstance()->getUserDynChannel(name);
if (args.size() < 3)
pass = name;
pass = toLower(name);
else
pass = args[2];

View file

@ -231,7 +231,7 @@ void cbClientConnection(CMessage& msgin, const std::string &serviceName, NLNET::
const bool betaTester = (userExtended.find(":FBT:") != string::npos);
const bool preOrder = (userExtended.find(":PO:") != string::npos);
const bool windermeerCommunity = (userExtended.find(":WIND:") != string::npos);
const bool trialPlayer = (userExtended.find(":TRIAL:") != string::npos);
const bool trialPlayer = (userExtended.find(":TRB:") != string::npos);
// load player infos
player = new CPlayer;

View file

@ -807,6 +807,16 @@ void CGuild::takeItem( CCharacter * user, uint32 slot, uint32 quantity, uint16 s
return;
}
// check if user is trial
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( user->getId() ));
BOMB_IF(p == NULL, "Failed to find player record for character: " << user->getId().toString(), return);
if ( p->isTrialPlayer() )
{
user->sendDynamicSystemMessage( user->getId(), "EGS_CANT_USE_GUILD_INV_IS_TRIAL_PLAYER" );
return;
}
CGuildMemberModule * module;
if ( !user->getModuleParent().getModule(module) || !module->canTakeGuildItem() )
{

View file

@ -90,6 +90,14 @@ void CGuildCharProxy::spendMoney(uint64 money)
_ModuleCore->spendMoney( money );
}
//----------------------------------------------------------------------------
bool CGuildCharProxy::isTrialPlayer()
{
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( getId() ));
BOMB_IF(p == NULL, "Failed to find player record for character: " << getId().toString(), return true);
return p->isTrialPlayer();
}
//----------------------------------------------------------------------------
void CGuildCharProxy::endBotChat()
{

View file

@ -55,6 +55,7 @@ public:
void sendDynamicMessageToChatGroup( const std::string & msg, CChatGroup::TGroupType type, const TVectorParamCheck & params = TVectorParamCheck() );
uint64 getMoney();
void spendMoney(uint64 money);
bool isTrialPlayer();
void endBotChat();
bool getTarget(CGuildCharProxy & proxy);
void setGuildId(uint32 guildId );

View file

@ -28,6 +28,7 @@
#include "mission_log.h"
#include "mission_manager/mission_manager.h"
#include "mission_manager/mission_parser.h"
#include "player_manager/player_manager.h"
#include "player_manager/character.h"
#include "player_manager/character_encyclopedia.h"
#include "mission_item.h"
@ -44,8 +45,9 @@
using namespace std;
using namespace NLMISC;
extern CVariable<sint32> MissionForcedSeason;
extern CVariable<bool> MissionPrerequisitsEnabled;
extern CVariable<sint32> MissionForcedSeason;
extern CVariable<bool> MissionPrerequisitsEnabled;
extern CPlayerManager PlayerManager;
NL_INSTANCE_COUNTER_IMPL(CMissionTemplate);
@ -179,6 +181,8 @@ bool CMissionTemplate::build(const NLLIGO::IPrimitive* prim,CMissionGlobalParsin
Prerequisits.GuildGrade = EGSPD::CGuildGrade::Unknown;
Prerequisits.TeamSize = 0;
Prerequisits.Season = EGSPD::CSeason::Invalid;
Prerequisits.CharacterMinAge = 0;
Prerequisits.MaxPlayerID = 0;
// init parsing vars
bool ret = true;
@ -528,7 +532,30 @@ bool CMissionTemplate::build(const NLLIGO::IPrimitive* prim,CMissionGlobalParsin
if (ret)
Prerequisits.EventFaction = CMissionParser::getNoBlankString( script[1] );
}
// character oldness check loading
else if ( script[0] == "req_character_age" )
{
sint age;
ret = parseInt( i+1, script,age ) && ret;
Prerequisits.CharacterMinAge = (uint32)age;
if ( Prerequisits.CharacterMinAge < 0 )
{
MISLOGERROR1("character minimum age is %d. Must be >= 0", Prerequisits.CharacterMinAge );
ret = false;
}
}
// maximum player ID check loading
else if ( script[0] == "req_max_player_id" )
{
sint max_id;
ret = parseInt( i+1, script,max_id ) && ret;
Prerequisits.MaxPlayerID = (uint32)max_id;
if ( Prerequisits.MaxPlayerID < 0 )
{
MISLOGERROR1("Maximum player ID is %u. Must be >= 0", Prerequisits.MaxPlayerID );
ret = false;
}
}
// update next step step text
else if ( script[0] == "set_obj" )
{
@ -2281,6 +2308,82 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
prereqInfos.Prerequisits.push_back(prereqDesc);
}
}
// check character minimum oldness
if( Prerequisits.CharacterMinAge > 0 )
{
prereqDesc.Validated = true;
uint32 minimumAge = Prerequisits.CharacterMinAge * 24 * 3600; // oldness required is given in days
uint32 characterAge = NLMISC::CTime::getSecondsSince1970() - user->getFirstConnectedTime();
nlwarning("%s Require character age of %d days (%ds) and current character age is %d", sDebugPrefix.c_str(),
Prerequisits.CharacterMinAge, minimumAge, characterAge);
if (characterAge < minimumAge)
{
if (logOnFail)
MISDBG("%s Require character age of %d days (%ds) and current character age is %d", sDebugPrefix.c_str(),
Prerequisits.CharacterMinAge, minimumAge, characterAge);
if (returnValue == MISSION_DESC::PreReqSuccess)
{
if (!fillPrereqInfos)
{return MISSION_DESC::PreReqFail;}
returnValue = MISSION_DESC::PreReqFail;
logOnFail = false;
}
prereqDesc.Validated = false;
}
if (fillPrereqInfos)
{
if (addedPrereqTexts.find("MISSION_PREREQ_CHARACTER_MIN_AGE") == addedPrereqTexts.end())
{
SM_STATIC_PARAMS_2(params, STRING_MANAGER::integer, STRING_MANAGER::integer);
params[0].Int = (uint32) (characterAge / (24 * 3600) );
params[1].Int = (uint32) Prerequisits.CharacterMinAge;
prereqDesc.Description = STRING_MANAGER::sendStringToClient(user->getEntityRowId(), "MISSION_PREREQ_CHARACTER_MIN_AGE", params);
prereqDesc.IsMandatory = true;
prereqInfos.Prerequisits.push_back(prereqDesc);
}
}
}
// check maximum player ID
if (Prerequisits.MaxPlayerID > 0)
{
prereqDesc.Validated = true;
uint32 playerId = PlayerManager.getPlayerId(user->getId());
nlwarning("%s Require player ID of %d and player's ID is %d", sDebugPrefix.c_str(),
Prerequisits.MaxPlayerID, playerId);
if (playerId > Prerequisits.MaxPlayerID )
{
if (logOnFail)
MISDBG("%s Require player ID of %d and player's ID is %d", sDebugPrefix.c_str(),
Prerequisits.MaxPlayerID, playerId);
if (returnValue == MISSION_DESC::PreReqSuccess)
{
if (!fillPrereqInfos)
{return MISSION_DESC::PreReqFail;}
returnValue = MISSION_DESC::PreReqFail;
logOnFail = false;
}
prereqDesc.Validated = false;
}
if (fillPrereqInfos)
{
if (addedPrereqTexts.find("MISSION_PREREQ_MAX_PLAYER_ID") == addedPrereqTexts.end())
{
prereqDesc.Description = STRING_MANAGER::sendStringToClient(user->getEntityRowId(), "MISSION_PREREQ_MAX_PLAYER_ID", TVectorParamCheck());
prereqDesc.IsMandatory = true;
prereqInfos.Prerequisits.push_back(prereqDesc);
}
}
}
}
if (returnValue == MISSION_DESC::PreReqSuccess)

View file

@ -242,13 +242,17 @@ public:
/// true if the player must be in a guild
bool Guild;
/// minimum guild grade displayed by the player
EGSPD::CGuildGrade::TGuildGrade GuildGrade;
EGSPD::CGuildGrade::TGuildGrade GuildGrade;
/// minimum team size
uint8 TeamSize;
/// actions that the player must know
std::vector<NLMISC::CSheetId> KnownActions;
/// The season that must be current
EGSPD::CSeason::TSeason Season;
EGSPD::CSeason::TSeason Season;
/// Character minimum oldness
uint32 CharacterMinAge;
/// minimum account id
uint32 MaxPlayerID;
// Requesite a specific thema of a specific album that all of its tasks are done
// or if TaskDone is false check if at least one is not done

View file

@ -207,7 +207,7 @@ extern vector<CMainlandSummary> Mainlands;
CVariable<uint32> SpawnedDeadMektoubDelay("egs","SpawnedDeadMektoubDelay", "nb tick before a dead mektoub despawn)", 2592000, 0, true );
CVariable<bool> ForceQuarteringRight("egs","ForceQuarteringRight", "Allow anyone to quarter a dead creature", false, 0, true );
CVariable<bool> AllowAnimalInventoryAccessFromAnyStable("egs", "AllowAnimalInventoryAccessFromAnyStable", "If true a player can access to his animal inventory (if the animal is inside a stable) from any stable over the world", true, 0, true );
CVariable<uint32> FreeTrialSkillLimit("egs", "FreeTrialSkillLimit", "Level limit for characters belonging to free trial accounts", 19,0,true);
CVariable<uint32> FreeTrialSkillLimit("egs", "FreeTrialSkillLimit", "Level limit for characters belonging to free trial accounts", 125,0,true);
CVariable<uint32> CraftFailureProbaMpLost("egs", "CraftFailureProbaMpLost", "Probabilité de destruction de chaque MP en cas d'echec du craft", 50,0,true);
@ -4050,6 +4050,7 @@ void CCharacter::initDatabase()
// combat flags
//_ForbidPowerDates.writeUsablePowerFlags(_UsablePowerFlags);
setPowerFlagDates();
setAuraFlagDates();
updateBrickFlagsDBEntry();
// defense interface
@ -5262,6 +5263,17 @@ bool CCharacter::checkAnimalCount( const CSheetId& PetTicket, bool sendMessage,
}
return false;
}
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( getId() ));
BOMB_IF(p == NULL,"Failed to find player record for character: "<<getId().toString(),return 0.0);
if ( p->isTrialPlayer() )
{
if( sendMessage )
{
sendDynamicSystemMessage( _Id, "EGS_CANT_BUY_PACKER_IS_TRIAL_PLAYER" );
}
return false;
}
}
else
{
@ -13885,7 +13897,7 @@ void CCharacter::setAuraFlagDates()
const NLMISC::TGameCycle time = CTickEventHandler::getGameCycle();
uint32 flag = BRICK_FLAGS::Aura - BRICK_FLAGS::BeginPowerFlags;
if ( _ForbidAuraUseEndDate > time )
if ( (_ForbidAuraUseEndDate > time) && (_ForbidAuraUseEndDate - time < 72000) )
{
_PowerFlagTicks[flag].StartTick = _ForbidAuraUseStartDate;
_PowerFlagTicks[flag].EndTick = _ForbidAuraUseEndDate;
@ -13895,7 +13907,6 @@ void CCharacter::setAuraFlagDates()
_PowerFlagTicks[flag].StartTick = 0;
_PowerFlagTicks[flag].EndTick = 0;
}
} // setAuraFlagDates //
@ -15687,10 +15698,15 @@ void CCharacter::sendCustomEmote( const NLMISC::CEntityId& id, MBEHAV::EBehaviou
if( behaviour != MBEHAV::IDLE )
{
setEmote( behaviour );
setAfkState(false);
}
string sEmoteCustomText = emoteCustomText.toUtf8();
if ((behaviour != MBEHAV::IDLE) || (sEmoteCustomText == "none"))
{
setAfkState(false);
}
if( sEmoteCustomText == "none" )
{
return;

View file

@ -221,6 +221,14 @@ bool CPlayerRoomInterface::canUseInventory(const CCharacter * owner, const CChar
if (owner != user)
return false;
CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( user->getId() ));
BOMB_IF(p == NULL, "Failed to find player record for character: " << user->getId().toString(), return true);
if ( p->isTrialPlayer() )
{
user->sendDynamicSystemMessage( user->getId(), "EGS_CANT_USE_ROOM_INV_IS_TRIAL_PLAYER" );
return false;
}
CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, user->getEntityRowId(), DSPropertyCELL );
const sint32 cell = mirrorCell;
if ( !CBuildingManager::getInstance()->isRoomCell(cell) )

View file

@ -20,6 +20,8 @@
#include "powers_and_auras.h"
#include "egs_sheets/egs_static_game_item.h"
#define MAX_ACTIVATION_DATE 72000 // 2h
#define MAX_DEACTIVATION_DATE 72000 // 2h
//-----------------------------------------------------------------------------
// CPowerActivationDate
@ -156,8 +158,24 @@ void CPowerActivationDateVector::activate()
while (it != PowerActivationDates.end())
{
(*it).DeactivationDate = time - (*it).DeactivationDate; // the value saved is time length since deactivation, here we transform length into a date
(*it).ActivationDate += time;
if ( ((*it).DeactivationDate >= 0) && ((*it).DeactivationDate < MAX_DEACTIVATION_DATE) )
{
(*it).DeactivationDate = time - (*it).DeactivationDate; // the value saved is time length since deactivation, here we transform length into a date
}
else
{
nlinfo("POWER_AURA_CONTROL : Bad Deactivation date : %d", (*it).DeactivationDate);
(*it).DeactivationDate = time - MAX_DEACTIVATION_DATE;
}
if ((*it).ActivationDate < MAX_ACTIVATION_DATE)
{
(*it).ActivationDate += time;
}
else
{
nlinfo("POWER_AURA_CONTROL : Bad Activation date : %d", (*it).ActivationDate);
(*it).ActivationDate = time;
}
++it;
}
doNotClear = false;
@ -214,7 +232,8 @@ void CAuraActivationDateVector::cleanVector()
}
else
{
++it;++itUser;
++it;
++itUser;
}
}
}
@ -249,7 +268,6 @@ bool CAuraActivationDateVector::isAuraEffective(POWERS::TPowerType type, const N
return result;
}
//-----------------------------------------------------------------------------
void CAuraActivationDateVector::activate()
{
@ -258,7 +276,17 @@ void CAuraActivationDateVector::activate()
while (it != _AuraActivationDates.end())
{
(*it).ActivationDate += time;
(*it).DeactivationDate = time - (*it).DeactivationDate; // the value saved is time length since deactivation, here we transform length into a date
if ((*it).ActivationDate < MAX_ACTIVATION_DATE)
{
(*it).ActivationDate += time;
}
else
{
nlinfo("POWER_AURA_CONTROL : Bad Activation date : %d", (*it).ActivationDate);
(*it).ActivationDate = time;
}
++it;
}
}
@ -321,7 +349,15 @@ void CConsumableOverdoseTimerVector::activate()
while (it != Dates.end())
{
(*it).ActivationDate += time;
if ((*it).ActivationDate < MAX_ACTIVATION_DATE)
{
(*it).ActivationDate += time;
}
else
{
nlinfo("POWER_AURA_CONTROL : Bad Activation date : %d", (*it).ActivationDate);
(*it).ActivationDate = time;
}
++it;
}
}

View file

@ -29,6 +29,26 @@ class CEntityBase;
class CGameItemPtr;
class IPVPInterface;
// Comparator for case-insensitive comparison in STL assos. containers
struct ci_less : std::binary_function<std::string, std::string, bool>
{
// case-independent (ci) compare_less binary function
struct nocase_compare : public std::binary_function<unsigned char,unsigned char,bool>
{
bool operator() (const unsigned char& c1, const unsigned char& c2) const
{
return tolower (c1) < tolower (c2);
}
};
bool operator() (const std::string & s1, const std::string & s2) const
{
return std::lexicographical_compare(
s1.begin (), s1.end (), // source range
s2.begin (), s2.end (), // dest range
nocase_compare ()); // comparison
}
};
/**
* CPVPManager2 singleton.
*
@ -41,7 +61,7 @@ class CPVPManager2
NL_INSTANCE_COUNTER_DECL(CPVPManager2);
public:
typedef std::map< PVP_CLAN::TPVPClan, TChanID > TMAPFactionChannel;
typedef std::map< std::string, TChanID > TMAPExtraFactionChannel;
typedef std::map< std::string, TChanID, ci_less > TMAPExtraFactionChannel; // Names are case-rententive but not case-sensitive
typedef std::map< TChanID, std::string > TMAPPassChannel;
///\name LOW LEVEL MANAGEMENT

View file

@ -541,6 +541,7 @@ void CInputOutputService::addCharacterName( const TDataSetRow& chId, const ucstr
CEntityId eid = TheDataset.getEntityId(chId);
ucstring oldname;
CCharacterInfos * charInfos = IOS->getCharInfos( eid, false );
if( charInfos == NULL )
{
@ -553,6 +554,7 @@ void CInputOutputService::addCharacterName( const TDataSetRow& chId, const ucstr
// remove previous name association
// _NameToInfos.erase(ucname);
_NameToInfos.erase(charInfos->ShortName.toUtf8());
oldname = charInfos->ShortName;
if (charInfos->EntityId != eid)
{
@ -599,6 +601,42 @@ void CInputOutputService::addCharacterName( const TDataSetRow& chId, const ucstr
break;
}
}
// See if an existing player was renamed
if (!oldname.empty())
{
TSessionId sessionid;
string name = charInfos->ShortName.toUtf8();
// Make sure that the short name contains the home session name, but only if the new name does not exist yet
// otherwise we will have problems. If the new name contains opening parentheses then don't add it because
// it will try to match it as a homeland name
string::size_type pos = name.find('(');
if (pos == string::npos)
{
name = CShardNames::getInstance().makeFullName(name, charInfos->HomeSessionId);
}
TCharInfoCont::iterator itInfos = _NameToInfos.find( name );
if( itInfos == _NameToInfos.end() )
{
// New name does not exist
charInfos->ShortName = ucstring(name);
}
// Save the old name only if new name is not found (and the player is getting original name back)
itInfos = _RenamedCharInfos.find( charInfos->ShortName.toUtf8() );
if( itInfos != _RenamedCharInfos.end() )
{
// New name was in the saved list; player is getting original name back.
// Remove the new name
_RenamedCharInfos.erase(charInfos->ShortName.toUtf8());
}
else
{
// New name was not in the list, save old name
_RenamedCharInfos.insert( make_pair(oldname.toUtf8(), charInfos) );
}
}
}
// try to map a translated bot name on the short name
@ -745,6 +783,13 @@ CCharacterInfos * CInputOutputService::getCharInfos( const ucstring& chName )
{
return itInfos->second;
}
// Not found so check any renamed players
itInfos = _RenamedCharInfos.find( chName.toUtf8() );
if( itInfos != _NameToInfos.end() )
{
return itInfos->second;
}
else
{
return NULL;

View file

@ -201,6 +201,8 @@ private:
/// infos on a character from his name
TCharInfoCont _NameToInfos;
/// Original information about renamed characters
TCharInfoCont _RenamedCharInfos;
typedef std::map<NLMISC::CEntityId, std::pair<NLMISC::TGameCycle, CCharacterInfos*> > TTempCharInfoCont;
/// Temporary storage for removed entities, will survive here for 3000 ticks.

View file

@ -68,6 +68,7 @@ std::string CStringManager::_LanguageCode[NB_LANGUAGES] =
"de",
"fr",
"ru",
"es",
/* ace: currently, we only want english, i remove other language to remove warning during IOS launch
"fr", // french

View file

@ -62,6 +62,7 @@ public:
german,
french,
russian,
spanish,
NB_LANGUAGES
};

View file

@ -366,10 +366,12 @@ namespace LS
{
nlwarning("on_login : Can't find ring user %u from account %u with GMId", otherUserId, userId);
}
else if (otherRu->getCurrentStatus() != TCurrentStatus::cs_offline) // cs_logged and cs_online
//else if (otherRu->getCurrentStatus() != TCurrentStatus::cs_offline) // cs_logged and cs_online
else if (otherRu->getCurrentStatus() == TCurrentStatus::cs_online) // less strict check, only avoid csr/player account logged on the same time
{
// DON'T check in the entity locator that the player is really online
//if (IEntityLocator::getInstance() && IEntityLocator::getInstance()->isUserOnline(otherUserId))
if (IEntityLocator::getInstance() && IEntityLocator::getInstance()->isUserOnline(otherUserId))
{
nldebug("LS : on_login : user %u already connected, rejecting login of %u with GMId", otherUserId, userId);
loginResult(from, userId, "", 3, toString("User %u (%u's GMId) already online", otherUserId, userId));
@ -392,10 +394,12 @@ namespace LS
{
nlwarning("on_login : Can't find ring user %u which GMID is account %u", otherUserId, userId);
}
else if (otherRu->getCurrentStatus() != TCurrentStatus::cs_offline) // cs_logged and cs_online
//else if (otherRu->getCurrentStatus() != TCurrentStatus::cs_offline) // cs_logged and cs_online
else if (otherRu->getCurrentStatus() == TCurrentStatus::cs_online) // less strict check, only avoid csr/player account logged on the same time
{
// DON'T check in the entity locator that the player is really online
//if (IEntityLocator::getInstance() && IEntityLocator::getInstance()->isUserOnline(otherUserId))
if (IEntityLocator::getInstance() && IEntityLocator::getInstance()->isUserOnline(otherUserId))
{
nldebug("LS : on_login : user %u already connected, rejecting login of %u which is the GMId of it", otherUserId, userId);
loginResult(from, userId, "", 4, toString("GM user %u (having GMId=%u) already online", otherUserId, userId));