Page 2 of 3

Re: Implementing: Rules System

Posted: Thu Jul 07, 2011 4:56 pm
by John Adams
Scatto, I know you said you are out the next few days. Is the Rules code in a state where I can start adding rule defs yet, or you want me to wait?

Re: Implementing: Rules System

Posted: Thu Jul 07, 2011 5:01 pm
by Scatman
You can certainly go ahead an add them.

Re: Implementing: Rules System

Posted: Thu Jul 21, 2011 5:53 pm
by John Adams
k, please tell me what I am doing wrong. Probably a simple thing.

I am adding a GLOBAL rule (I cannot use the enum "WORLD" for some reason, so I am using the enum GLOBAL for category). This rule is NOT related to a zone, but world-wide. Ie., I want it to be applied everywhere, not just 1 zone.

Code: Select all

enum RuleCategory {
	CHARACTER,
	GLOBAL,
	ZONE
};

enum RuleType {
	MAX_LEVEL,
	SERVER_GUILD_AUTOJOIN,
	SERVER_GUILD_ID,
	XP_MULTIPLIER,
	XP_TRADESKILL_MULTIPLIER
};
The rule is:
GLOBAL, SERVER_GUILD_AUTOJOIN, 0

I got the enum part, the rule seems to exist.

Now I am in WorldDatabase::SaveCharacter(...) trying to access this rule to see if it is set to 0 or 1.
If it is set to 0, SaveCharacter should continue.
If it is set to 1, SaveCharacter should perform the task of adding that newly created character to the Guild ID 1.

However, 10,000 ways I've tried, I cannot simply check if the GLOBAL rule has a value. I've tried the examples, but the example was how to do it on a ZONE only, not world-wide/GLOBAL.

Everything is saying "not a member", the -> doesn't work, and when I try rule_manager.GetRules(...), I am not allowed to put anything in the (). too many arguments. blah blah blah.


Frustrated, because I'm sure it's simple and I just can't figure it out. Sigh. Sorry.

Re: Implementing: Rules System

Posted: Sun Jul 24, 2011 3:44 pm
by John Adams
Ahem...

Anyone home?

Re: Implementing: Rules System

Posted: Sun Jul 24, 2011 6:03 pm
by Scatman
Ah, thought you wanted to start with zone rules first. I just need to add a function for it. I didn't want to implement the entire thing before you played around with it and gave me the OK and/or some modifications :P

It'd simply be a getting like GetZoneRule() but without the zone id. It'll take me 2 seconds to do and I'll be home tomorrow to do it.

Re: Implementing: Rules System

Posted: Mon Jul 25, 2011 8:55 am
by John Adams
Ok, so I was not out of my mind ;)

Nah, I thought I said World (global) first, Zones and Locations (areas) after... but either way is fine. Let me know when/if you have time for this anytime soon. I think I'm done beating my head against a wall for a while... need to heal.

Re: Implementing: Rules System

Posted: Mon Jul 25, 2011 2:36 pm
by Scatman
So where exactly are the global variables being set in the db again?

Re: Implementing: Rules System

Posted: Tue Jul 26, 2011 7:33 am
by John Adams
JA POST, INC!!!
Zcoretri might as well stop reading right now...

Let's take a look at this from the parent->child->grandchild model.

World Rules
Everything should start at the World level. Every single rule is a World (Global) rule, and will be applied everywhere. The default ruleset will be defined in code, and mimicked in the database as "ruleset_id 1", our Default Rule Set. This is our Parent ruleset. The World knows what it's BASE, Global ruleset_id is because it is set in the `variables` table (default_ruleset_id = 1).

World starts, sees what it's default_ruleset_id is, loads that ruleset either from the DB (if it exists) or if not, just applies the defined defaults in code.


Zone Rules
Later, if we choose, we can opt to configure a Child (Zone) ruleset, which is based on the Parent (Global) ruleset. The Child ruleset will only have categories/types/values that are DIFFERENT than the Parent ruleset, and applied only to that Zone.
  • Meaning, if we change the NPC::AGGRO_RADIUS rule in Zone ID 1 to 50 feet vs the standard 10 feet for Zone ID 1, then a new ruleset_id is created (ruleset_id 2) and zone ID 1 gets assigned that 1 single new rule in the tables. When that zone loads, ALL DEFAULT RULES are applied, and this 1 single override is then applied after.

Area Rules
Grandchild refers to Areas, and we can discuss that much later because it's nothing I am overly interested in configuring right this moment. Just keep it in mind if you will.


Example Data
Take a look again at how EQEmu's table data looks, and know this is an exact copy of what is defined in their code as well. I want to do the same thing, even if it seems redundant, I just want the defaults to be in the DB too for ease of overview and editing by non-Project server admins.

EQEmu comes packaged with 1 default ruleset -

table: rule_set

Code: Select all

ruleset_id, name
1, default_set

With these rule values -

table: rule_values

Code: Select all

ruleset_id, rule_name, rule_value
1, AA:ExpPerPoint, 23976503
1, Aggro:CriticallyWoundedAggroMod, 100
1, Aggro:CurrentTargetAggroMod, 0
1, Aggro:IncapacitateAggroMod, 500
1, Aggro:MeleeRangeAggroMod, 10
1, Aggro:MovementImpairAggroMod, 175
1, Aggro:PetSpellAggroMod, 10
1, Aggro:SittingAggroMod, 35
1, Aggro:SlowAggroMod, 450
1, Aggro:SmartAggroList, true
1, Aggro:SongAggroMod, 33
1, Aggro:SpellAggroMod, 100
1, Aggro:StunAggroMod, 750
1, Bazaar:AuditTrail, false
1, Bazaar:EnableWarpToTrader, true
1, Bazaar:MaxBarterSearchResults, 200
1, Bazaar:MaxSearchResults, 50
1, Channels:DeleteTimer, 1440
1, Channels:RequiredStatusAdmin, 251
1, Channels:RequiredStatusListAll, 251
1, Character:AAExpMultiplier, 0.5
1, Character:AutosaveIntervalS, 300
1, Character:BindAnywhere, false
1, Character:ConsumptionMultiplier, 100
1, Character:CorpseDecayTimeMS, 10800000
1, Character:CorpseResTimeMS, 10800000
1, Character:DeathExpLossLevel, 10
1, Character:DeathExpLossMaxLevel, 255
1, Character:DeathExpLossMultiplier, 3
1, Character:DeathItemLossLevel, 10
1, Character:DragCorpseDistance, 400.000000
1, Character:EnduranceRegenMultiplier, 100
1, Character:ExpMultiplier, 0.5
1, Character:FeignKillsPet, false
1, Character:GroupExpMultiplier, 0.5
1, Character:HasteCap, 100
1, Character:HealOnLevel, false
1, Character:HPRegenMultiplier, 100
1, Character:ItemAccuracyCap, 150
1, Character:ItemAvoidanceCap, 100
1, Character:ItemCastsUseFocus, false
1, Character:ItemClairvoyanceCap, 250
1, Character:ItemCombatEffectsCap, 100
1, Character:ItemDamageShieldCap, 30
1, Character:ItemDoTShieldingCap, 35
1, Character:ItemDSMitigationCap, 50
1, Character:ItemEnduranceRegenCap, 15
1, Character:ItemHealAmtCap, 250
1, Character:ItemHealthRegenCap, 35
1, Character:ItemManaRegenCap, 15
1, Character:ItemShieldingCap, 35
1, Character:ItemSpellDmgCap, 250
1, Character:ItemSpellShieldingCap, 35
1, Character:ItemStrikethroughCap, 35
1, Character:ItemStunResistCap, 35
1, Character:KillsPerGroupLeadershipAA, 50
1, Character:KillsPerRaidLeadershipAA, 50
1, Character:LeaveCorpses, false
1, Character:LeaveNakedCorpses, false
1, Character:ManaRegenMultiplier, 100
1, Character:MaxDraggedCorpses, 2
1, Character:MaxExpLevel, 0
1, Character:MaxLevel, 80
1, Character:MinStatusForNoDropExemptions, 80
1, Character:RaidExpMultiplier, 0.2
1, Character:RespawnFromHover, true
1, Character:RespawnFromHoverTimer, 300
1, Character:RestRegenEndurance, false
1, Character:RestRegenPercent, 0
1, Character:RestRegenTimeToActivate, 30
1, Character:SharedBankPlat, false
1, Character:SkillCapMaxLevel, -1
1, Character:SkillUpModifier, 100
1, Character:SoDClientUseSoDHPManaEnd, false
1, Character:StatCap, 0
1, Character:UseDeathExpLossMult, true
1, Character:UseNewStatsWindow, true
1, Character:UseRaceClassExpBonuses, true
1, Chat:EnableMailKeyIPVerification, false
1, Chat:EnableVoiceMacros, false
1, Chat:ServerWideAuction, true
1, Chat:ServerWideOOC, true
1, Combat:AdjustProcPerMinute, true
1, Combat:AgiHitFactor, 0.01
1, Combat:ArcheryBaseDamageBonus, 1
1, Combat:ArcheryHitPenalty, 0.25
1, Combat:ArcheryNPCMultiplier, 1.0
1, Combat:ArcheryStationaryPenalty, 1.0
1, Combat:AssistNoTargetSelf, true
1, Combat:AvgProcsPerMinute, 18.0
1, Combat:BaseHitChance, 69
1, Combat:BaseProcChance, 0.035
1, Combat:BerserkBaseCritChance, 6
1, Combat:CasterHitChanceMod, 0.7
1, Combat:ClientBaseCritChance, 0
1, Combat:EnableFearPathing, true
1, Combat:FleeHPRatio, 25
1, Combat:FleeIfNotAlone, false
1, Combat:HeavyAvoidChanceMod, 1.0
1, Combat:HitBonusPerLevel, 0.4
1, Combat:HitFalloffMajor, 50.0
1, Combat:HitFalloffMinor, 5.0
1, Combat:HitFalloffModerate, 7.0
1, Combat:HitPerLevelDiff, 145
1, Combat:LightAvoidChanceMod, 0.91
1, Combat:MeleeBaseCritChance, 0
1, Combat:MeleeHitChanceMod, 1.0
1, Combat:MinRangedAttackDist, 25
1, Combat:ModerateAvoidChanceMod, 0.96
1, Combat:NPCBashKickLevel, 6
1, Combat:NPCBashKickStunChance, 15
1, Combat:PetAttackMagicLevel, 30
1, Combat:PriestHitChanceMod, 0.85
1, Combat:ProcDexDivideBy, 11000
1, Combat:ProcPerMinDexContrib, 0.075
1, Combat:UnarmoredAvoidChanceMod, 0.86
1, Combat:UseIntervalAC, true
1, Combat:WarBerBaseCritChance, 3
1, Combat:WeaponSkillFalloff, 0.33
1, EventLog:RecordBuyFromMerchant, false
1, EventLog:RecordSellToMerchant, false
1, GM:MinStatusToZoneAnywhere, 250
1, Guild:MaxMembers, 2048
1, Mail:EnableMailSystem, true
1, Mail:ExpireRead, 31536000
1, Mail:ExpireTrash, 0
1, Mail:ExpireUnread, 31536000
1, Map:FindBestZHeightAdjust, 1
1, Map:FixPathingZAtWaypoints, false
1, Map:FixPathingZMaxDeltaLoading, 45.0000000
1, Map:FixPathingZMaxDeltaMoving, 20.0000000
1, Map:FixPathingZMaxDeltaSendTo, 20.0000000
1, Map:FixPathingZMaxDeltaWaypoint, 20.0000000
1, Map:FixPathingZOnSendTo, false
1, Map:FixPathingZWhenLoading, true
1, Map:FixPathingZWhenMoving, false
1, Map:UseClosestZ, false
1, Merchant:BuyCostMod, 0.95
1, Merchant:ChaBonusMod, 3.45
1, Merchant:ChaPenaltyMod, 1.52
1, Merchant:PriceBonusPct, 4
1, Merchant:PricePenaltyPct, 4
1, Merchant:SellCostMod, 1.05
1, Merchant:UsePriceMod, true
1, NPC:BuffFriends, false
1, NPC:CorpseUnlockTimer, 150000
1, NPC:EmptyNPCCorpseDecayTimeMS, 0
1, NPC:EnableNPCQuestJournal, false
1, NPC:LastFightingDelayMovingMax, 20000
1, NPC:LastFightingDelayMovingMin, 10000
1, NPC:MajorNPCCorpseDecayTimeMS, 1500000
1, NPC:MinorNPCCorpseDecayTimeMS, 450000
1, NPC:OOCRegen, 0
1, NPC:ReturnNonQuestNoDropItems, false
1, NPC:SayPauseTimeInSec, 5
1, NPC:SmartLastFightingDelayMoving, true
1, NPC:UseItemBonusesForNonPets, true
1, Pathing:Aggro, true
1, Pathing:AggroReturnToGrid, true
1, Pathing:CandidateNodeRangeXY, 400.000000
1, Pathing:CandidateNodeRangeZ, 10.0000000
1, Pathing:CullNodesFromEnd, 1
1, Pathing:CullNodesFromStart, 1
1, Pathing:Fear, true
1, Pathing:Find, true
1, Pathing:Guard, true
1, Pathing:LOSCheckFrequency, 1000
1, Pathing:MaxNodesLeftForLOSCheck, 4
1, Pathing:MinDistanceForLOSCheckLong, 1000000.00
1, Pathing:MinDistanceForLOSCheckShort, 40000.0000
1, Pathing:MinNodesTraversedForLOSCheck, 3
1, Pathing:RouteUpdateFrequencyLong, 5000
1, Pathing:RouteUpdateFrequencyNodeCount, 5
1, Pathing:RouteUpdateFrequencyShort, 1000
1, Pathing:ZDiffThreshold, 10.0000000
1, Pets:AttackCommandRange, 150.000000
1, Skills:MaxTradeskillSearchSkillDiff, 50
1, Skills:MaxTrainTradeskills, 21
1, Skills:UseLimitTradeskillSearchSkillDiff, true
1, Spells:AutoResistDiff, 15
1, Spells:BaseCritChance, 0
1, Spells:BaseCritRatio, 100
1, Spells:EnableBlockedBuffs, true
1, Spells:EnableSpellGlobals, false
1, Spells:PartialHitChance, 0.69999998
1, Spells:PartialHitChanceFear, 0.25000000
1, Spells:ReflectType, 1
1, Spells:ResistChance, 2.00000000
1, Spells:ResistMod, 0.40000000
1, Spells:ResistPerLevelDiff, 85
1, Spells:SacrificeItemID, 9963
1, Spells:SacrificeMaxLevel, 69
1, Spells:SacrificeMinLevel, 46
1, Spells:TranslocateTimeLimit, 0
1, Spells:VirusSpreadDistance, 30
1, Spells:WizCritChance, 7
1, Spells:WizCritLevel, 12
1, Spells:WizCritRatio, 0
1, TaskSystem:EnableTaskProximity, true
1, TaskSystem:EnableTaskSystem, true
1, TaskSystem:KeepOneRecordPerCompletedTask, true
1, TaskSystem:PeriodicCheckTimer, 5
1, TaskSystem:RecordCompletedOptionalActivities, false
1, TaskSystem:RecordCompletedTasks, true
1, Watermap:CheckForWaterAtWaypoints, false
1, Watermap:CheckForWaterOnSendTo, false
1, Watermap:CheckForWaterWhenFishing, false
1, Watermap:CheckForWaterWhenMoving, false
1, Watermap:CheckWaypointsInWaterWhenLoading, false
1, Watermap:FishingLineLength, 40.0000000
1, Watermap:FishingRodLength, 30.0000000
1, World:AccountSessionLimit, -1
1, World:AddMaxClientsPerIP, -1
1, World:AddMaxClientsStatus, -1
1, World:ClearTempMerchantlist, true
1, World:ClientKeepaliveTimeoutMS, 65000
1, World:EnableReturnHomeButton, true
1, World:EnableTutorialButton, true
1, World:ExemptAccountLimitStatus, -1
1, World:ExemptMaxClientsStatus, -1
1, World:ExpansionSettings, 16383
1, World:FVNoDropFlag, 0
1, World:GMAccountIPList, false
1, World:GuildBankZoneID, 345
1, World:IsGMPetitionWindowEnabled, false
1, World:MaxClientsPerIP, -1
1, World:MaxClientsSetByStatus, false
1, World:MaxLevelForTutorial, 10
1, World:MinOfflineTimeToReturnHome, 21600
1, World:PVPSettings, 0
1, World:SoFStartZoneID, -1
1, World:TutorialZoneID, 189
1, World:UseBannedIPsTable, true
1, World:ZoneAutobootTimeoutMS, 60000
1, Zone:AutoShutdownDelay, 5000
1, Zone:ClientLinkdeadMS, 180000
1, Zone:EnableMQGateDetector, true
1, Zone:EnableMQGhostDetector, true
1, Zone:EnableMQWarpDetector, true
1, Zone:EnableMQZoneDetector, true
1, Zone:EnableShadowrest, false
1, Zone:GraveyardTimeMS, 1200000
1, Zone:MQGateExemptStatus, -1
1, Zone:MQGhostExemptStatus, -1
1, Zone:MQWarpDetectorDistance, 4900.00000
1, Zone:MQWarpExemptStatus, -1
1, Zone:MQWarpLagThreshold, 140.000000
1, Zone:MQWarpThresholdTimer, 90000.0000
1, Zone:MQZoneExemptStatus, -1
1, Zone:NPCGlobalPositionUpdateInterval, 60000
1, Zone:PEQZoneDebuff1, 4454
1, Zone:PEQZoneDebuff2, 2209
1, Zone:PEQZoneReuseTime, 900
1, Zone:UsePEQZoneDebuffs, true
Does this make more sense, why I wanted to start with World (global) first? Btw, I cannot create a category called "WORLD" because it must already be defined somewhere else, because it errors when I try making it an ENUM.

Btw, while I like the ENUM concept, I am worried that you are thinking the Category ZONE *must* be a zone-rule only, and it is not. It is a World-wide rule for all zones. The only time a rule becomes specific to a zone is if the entire ruleset is bound to a zone via `zones`.`ruleset_id`.

Hope this isn't more confusing... sorry. Just woke up. :mrgreen:

Re: Implementing: Rules System

Posted: Tue Jul 26, 2011 7:39 am
by John Adams
Scatman wrote:So where exactly are the global variables being set in the db again?
Did that answer *this* question? Or TMI, as usual from me? tee

Re: Implementing: Rules System

Posted: Tue Jul 26, 2011 3:34 pm
by Scatman
John Adams wrote:The World knows what it's BASE, Global ruleset_id is because it is set in the `variables` table (default_ruleset_id = 1).
That's all I needed to know! :D Gotta mow the lawn then I'll add it.
John Adams wrote:Does this make more sense, why I wanted to start with World (global) first? Btw, I cannot create a category called "WORLD" because it must already be defined somewhere else, because it errors when I try making it an ENUM.
Probably from the pre-processor definition WORLD (LOGIN, etc).
John Adams wrote:Btw, while I like the ENUM concept, I am worried that you are thinking the Category ZONE *must* be a zone-rule only, and it is not. It is a World-wide rule for all zones. The only time a rule becomes specific to a zone is if the entire ruleset is bound to a zone via `zones`.`ruleset_id`.
Yep, that's exactly how the rules are implemented. Give me CHARACTER and MAX_LEVEL for zone id 253. If that rule isn't found in the rule set for zone 253, give me the default rule.

Re: Implementing: Rules System

Posted: Tue Jul 26, 2011 7:00 pm
by Scatman
It's committed. rule_manager.GetGlobalRule(cat,type). I didn't see any initial problems, but once it gets passed JA testing, I'll be confident it's ok :P

Re: Implementing: Rules System

Posted: Tue Jul 26, 2011 7:33 pm
by John Adams
Haha thanks Scattomundo! I will take a look at it this week/weekend. Getting ass-pounded at work, again... and not in the way I prefer.

Re: Implementing: Rules System

Posted: Wed Jul 27, 2011 7:46 am
by John Adams
Question 1:
Another quick questions, Scatto. If I wanted to iterate through all current, active rules (globally, or in a zone), how would I do that?

IE., making a ConsoleCommand called: 'rules' with params [all | zone] {id}

so I would type

rules global (or just rules alone and it assumes global) and it will display all current set global rules to the console.

or

rules zone 253
and it will display only rules specific to zone ID 253

I'm tinkering with it today, but will wait for your feedback before wasting my entire day hacking something together that you'll tell me is 2 lines of code ;)



Question 2:

for these:

Code: Select all

enum RuleType {
	/* UI */
	MAX_WHO_RESULTS,
	MAX_WHO_OVERRIDE_STATUS,

Can I actually use CamelCaseNames instead of CONSTANT_LOOKING_HORRIBLE_SCREAMING_VARIABLE_NAMES?

:wink:

EDIT: Well I managed to try this latter question, and it does compile. So it must work!!

Code: Select all

enum RuleType {
	/* UI */
	MaxWhoResults,
	MaxWhoOverrideStatus,

Re: Implementing: Rules System

Posted: Wed Jul 27, 2011 2:56 pm
by John Adams
Bug 1: We need to handle this scenario we talked about... where some dumbass (me) calls to an invalid Category, Type combo.

Replaced `variables` settings in LoginServer::InitLoginServerVariables(), the first sInt16 sets fine, but the other 2 shit the bed.

Code: Select all

minLockedStatus   = rule_manager.GetGlobalRule(R_World, ServerLockedOverrideStatus)->GetSInt16();
maxPlayers	     = rule_manager.GetGlobalRule(R_World, MaxPlayers)->GetSInt16();
minGameFullStatus = rule_manager.GetGlobalRule(R_World, MaxPlayersOverrideStatus)->GetSInt16();
Reason why:

Code: Select all

	RULE_INIT(R_Player, MaxPlayers, "-1");
	RULE_INIT(R_Player, MaxPlayersOverrideStatus, "100");
MaxPlayers* is not an R_World category. Oops! But yeah, we should not Crash cuz of it. Ideas how to stop that from happening, and just report "Hey dumbass, invalid Rule!"?

Re: Implementing: Rules System

Posted: Wed Jul 27, 2011 6:36 pm
by Scatman
Question 1:
I haven't done commands yet. Before I implement the in-game commands, I wanted to make sure you were happy with the rule system so if I do need to change something, I don't have to change a gazillion commands. But we'll definitely be able to do something like that.

Question 2:
Yeah you do format them however you'd like.
John Adams wrote:Bug 1: We need to handle this scenario we talked about... where some dumbass (me) calls to an invalid Category, Type combo.
Ok, good catch. Don't add anymore Rule getting into world yet. I'm going to change how you access a rule. Instead of rule_manager.GetZoneRule(cat,type)->GetInt16(), it'll be...rule_manager->GoneRuleInt16(cat, type). This way I can return a default type instead of returning NULL for the rule and crashing world. So integers will return 0, strings will return "", etc. Sound good?