From 2f5909d4cbf5ee4f4f87cd781e9d1803dab8cf80 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 14:20:18 -0500 Subject: [PATCH 1/9] Implement AA timers reset on death This is a field in the packet, live only uses this for Lay on Hands Currently I didn't add this to the packet since it has 0 effect on the client. We could move this field to aa_ranks which would give more flexibility for custom servers, but no one said they wanted it there. --- common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod_structs.h | 2 +- common/patches/sof_structs.h | 2 +- common/patches/uf_structs.h | 2 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2020_02_06_aa_reset_on_death.sql | 2 ++ zone/aa.cpp | 23 +++++++++++++++++-- zone/aa_ability.h | 1 + zone/attack.cpp | 5 ++++ zone/client.h | 1 + 12 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 utils/sql/git/required/2020_02_06_aa_reset_on_death.sql diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index cecafb767..10ce35654 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4401,7 +4401,7 @@ struct SendAA_Struct { /*0104*/ uint32 special_category; /*0108*/ uint8 shroud; /*0109*/ uint8 unknown109; -/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0110*/ uint8 reset_on_death; // timer is reset on death /*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 7f466f09b..03f1a951a 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4341,7 +4341,7 @@ struct SendAA_Struct { /*0104*/ uint32 special_category; /*0108*/ uint8 shroud; /*0109*/ uint8 unknown109; -/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0110*/ uint8 reset_on_death; // timer is reset on death /*0111*/ uint8 unknown111; /*0112*/ uint32 total_abilities; /*0116*/ AA_Ability abilities[0]; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 0803432db..76a534e6a 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -3780,7 +3780,7 @@ struct SendAA_Struct { /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; /*0097*/ uint8 unknown97; -/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0098*/ uint8 reset_on_death; // timer is reset on death /*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 0b175b643..1507630bd 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3704,7 +3704,7 @@ struct SendAA_Struct { /*0088*/ uint32 aa_expansion; /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; -/*0097*/ uint8 unknown97; +/*0097*/ uint8 reset_on_death; // timer is reset on death -- guess /*0098*/ uint32 total_abilities; /*0102*/ AA_Ability abilities[0]; }; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index e165da794..b6eb414e1 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -3835,7 +3835,7 @@ struct SendAA_Struct { /*0092*/ uint32 special_category; /*0096*/ uint8 shroud; /*0097*/ uint8 unknown97; -/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter? +/*0098*/ uint8 reset_on_death; // timer is reset on death /*0099*/ uint8 unknown99; /*0100*/ uint32 total_abilities; /*0104*/ AA_Ability abilities[0]; diff --git a/common/version.h b/common/version.h index 13579c3d2..a950edbe0 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9149 +#define CURRENT_BINARY_DATABASE_VERSION 9150 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index fdaa4a946..9d0aa9231 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -403,6 +403,7 @@ 9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty| 9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty| 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| +9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql b/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql new file mode 100644 index 000000000..91edb5d4a --- /dev/null +++ b/utils/sql/git/required/2020_02_06_aa_reset_on_death.sql @@ -0,0 +1,2 @@ +ALTER TABLE `aa_ability` ADD `reset_on_death` TINYINT(4) NOT NULL DEFAULT '0'; +UPDATE `aa_ability` SET `reset_on_death` = '1' WHERE `id` = 6001; diff --git a/zone/aa.cpp b/zone/aa.cpp index 1383ad2f9..1ccc6f656 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1023,6 +1023,24 @@ void Client::ResetAlternateAdvancementTimers() { safe_delete(outapp); } +void Client::ResetOnDeathAlternateAdvancement() { + for (const auto &aa : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if (!ability) + continue; + + if (!rank) + continue; + + // since they're dying, we just need to clear the DB + if (ability->reset_on_death) + p_timers.Clear(&database, rank->spell_type + pTimerAAStart); + } +} + void Client::PurchaseAlternateAdvancementRank(int rank_id) { AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); if(!rank) { @@ -1646,7 +1664,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_maptype = atoi(row[8]); ability->charges = atoi(row[9]); ability->grant_only = atoi(row[10]) != 0 ? true : false; - ability->first_rank_id = atoi(row[11]); + ability->reset_on_death = atoi(row[11]) != 0 ? true : false; + ability->first_rank_id = atoi(row[12]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); diff --git a/zone/aa_ability.h b/zone/aa_ability.h index 0d6a240c4..5ec08d986 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -50,6 +50,7 @@ public: int drakkin_heritage; int status; bool grant_only; + bool reset_on_death; int type; int charges; int first_rank_id; diff --git a/zone/attack.cpp b/zone/attack.cpp index 083176e39..bd169908c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1852,6 +1852,11 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk BuffFadeDetrimental(); } + /* + Reset AA reuse timers that need to be, live-like this is only Lay on Hands + */ + ResetOnDeathAlternateAdvancement(); + /* Finally, send em home diff --git a/zone/client.h b/zone/client.h index a0655584b..030484229 100644 --- a/zone/client.h +++ b/zone/client.h @@ -838,6 +838,7 @@ public: void SendAlternateAdvancementTimers(); void ResetAlternateAdvancementTimer(int ability); void ResetAlternateAdvancementTimers(); + void ResetOnDeathAlternateAdvancement(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } From 29fccd923924638613be36fb269e1672970dfe37 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 6 Feb 2020 16:44:46 -0500 Subject: [PATCH 2/9] LoH skill needs to be reset on death --- zone/attack.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/attack.cpp b/zone/attack.cpp index bd169908c..4da160608 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1857,6 +1857,12 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk */ ResetOnDeathAlternateAdvancement(); + /* + Reset reuse timer for classic skill based Lay on Hands (For tit I guess) + */ + if (GetClass() == PALADIN) // we could check if it's not expired I guess, but should be fine not to + p_timers.Clear(&database, pTimerLayHands); + /* Finally, send em home From 5f8d193d6a68eb5e7e0fb45451d2ec0125264a24 Mon Sep 17 00:00:00 2001 From: Xackery Xtal Date: Sat, 8 Feb 2020 18:01:46 -0800 Subject: [PATCH 3/9] Added EnableFoodRequirement --- common/ruletypes.h | 1 + zone/client.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 8e5793bc3..4284e0d0b 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -121,6 +121,7 @@ RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap") RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update") RULE_BOOL(Character, EnableHungerPenalties, false, "being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties") +RULE_BOOL(Character, EnableFoodRequirement, true, "if disabled, food is no longer required") RULE_INT(Character, BaseInstrumentSoftCap, 36, "Softcap for instrument mods, 36 commonly referred to as \"3.6\" as well") RULE_BOOL(Character, UseSpellFileSongCap, true, "When they removed the AA that increased the cap they removed the above and just use the spell field") RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225") diff --git a/zone/client.h b/zone/client.h index 030484229..52af842be 100644 --- a/zone/client.h +++ b/zone/client.h @@ -901,14 +901,14 @@ public: void BreakFeignDeathWhenCastOn(bool IsResisted); void LeaveGroup(); - bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;} - bool Thirsty() const {if (GetGM()) return false; return m_pp.thirst_level <= 3000;} + bool Hungry() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.hunger_level <= 3000;} + bool Thirsty() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.thirst_level <= 3000;} int32 GetHunger() const { return m_pp.hunger_level; } int32 GetThirst() const { return m_pp.thirst_level; } void SetHunger(int32 in_hunger); void SetThirst(int32 in_thirst); void SetConsumption(int32 in_hunger, int32 in_thirst); - bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } + bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } bool CheckTradeLoreConflict(Client* other); bool CheckTradeNonDroppable(); From 709a25ba9e79652faa85c980c66e2e29fe885058 Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Sat, 15 Feb 2020 16:55:18 -0800 Subject: [PATCH 4/9] Add necro pet spell effect id to pet spell reagent check --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index a1e926a1c..1724f51b0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1230,7 +1230,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo // handle the components for traditional casters else { - if (!RuleB(Character, PetsUseReagents) && IsEffectInSpell(spell_id, SE_SummonPet)) { + if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SE_SummonPet) || IsEffectInSpell(spell_id, SE_NecPet))) { //bypass reagent cost } else if(c->GetInv().HasItem(component, component_count, invWhereWorn|invWherePersonal) == -1) // item not found From 5901df44851a548acc428277b16540878adb0c23 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 16 Feb 2020 11:41:08 -0500 Subject: [PATCH 5/9] Added Skills, RequireTomeHandin rule Default behavior will remain the same as current code. If set to true, tomes will need to be turned in to Guild Masters to learn, like in older times. --- common/ruletypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 4284e0d0b..a9f7a233f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -88,7 +88,6 @@ RULE_INT(Character, ItemHealAmtCap, 250, "") RULE_INT(Character, ItemSpellDmgCap, 250, "") RULE_INT(Character, ItemClairvoyanceCap, 250, "") RULE_INT(Character, ItemDSMitigationCap, 50, "") -RULE_INT(Character, ItemEnduranceRegenCap, 15, "") RULE_INT(Character, ItemExtraDmgCap, 150, "Cap for bonuses to melee skills like Bash, Frenzy, etc") RULE_INT(Character, HasteCap, 100, "Haste cap for non-v3(overhaste) haste") RULE_INT(Character, SkillUpModifier, 100, "skill ups are at 100%") @@ -197,6 +196,7 @@ RULE_INT(Skills, SwimmingStartValue, 100, "") RULE_BOOL(Skills, TrainSenseHeading, false, "") RULE_INT(Skills, SenseHeadingStartValue, 200, "") RULE_BOOL(Skills, SelfLanguageLearning, true, "") +RULE_BOOL(Skills, RequireTomeHandin, false, "Disable click-to-learn and force turnin to Guild Master") RULE_CATEGORY_END() RULE_CATEGORY(Pets) From bd4fa4fb6b790b76b33573beb27770489fb5ca04 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 16 Feb 2020 11:42:55 -0500 Subject: [PATCH 6/9] Implement RuleB(Skills, RequireTomeHandin) --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0ea11e8ae..7173dd342 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8653,7 +8653,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else if (inst->IsClassCommon()) { - if (item->ItemType == EQEmu::item::ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: "))) + if (!RuleB(Skills, RequireTomeHandin) && item->ItemType == EQEmu::item::ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: "))) { DeleteItemInInventory(slot_id, 1, true); TrainDiscipline(item->ID); From 141ecca2bcae65f4a395574522e69adb4f18263d Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Sun, 16 Feb 2020 09:23:26 -0800 Subject: [PATCH 7/9] Add necromancer pet spell check to other reagent logic --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 1724f51b0..5b8ee33f8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1263,7 +1263,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo return; } } - else if (!RuleB(Character, PetsUseReagents) && IsEffectInSpell(spell_id, SE_SummonPet)) { + else if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SE_SummonPet) || IsEffectInSpell(spell_id, SE_NecPet))) { //bypass reagent cost } else if (!bard_song_mode) From 10e5f0e9496887d04246a6e9bc15318d60c38b7a Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 16 Feb 2020 12:28:18 -0500 Subject: [PATCH 8/9] Update ruletypes.h --- common/ruletypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index a9f7a233f..b15d3fbf7 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -88,6 +88,7 @@ RULE_INT(Character, ItemHealAmtCap, 250, "") RULE_INT(Character, ItemSpellDmgCap, 250, "") RULE_INT(Character, ItemClairvoyanceCap, 250, "") RULE_INT(Character, ItemDSMitigationCap, 50, "") +RULE_INT(Character, ItemEnduranceRegenCap, 15, "") RULE_INT(Character, ItemExtraDmgCap, 150, "Cap for bonuses to melee skills like Bash, Frenzy, etc") RULE_INT(Character, HasteCap, 100, "Haste cap for non-v3(overhaste) haste") RULE_INT(Character, SkillUpModifier, 100, "skill ups are at 100%") From 6fb0042e3f5c33ee1b2915f9fbb93328b4d33221 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 18 Feb 2020 15:50:01 -0500 Subject: [PATCH 9/9] Add packet struct and ops for AdvancedLoreText Just stuff if people want to start working on it --- common/eq_packet_structs.h | 7 +++++++ utils/patches/patch_RoF.conf | 2 +- utils/patches/patch_RoF2.conf | 2 ++ utils/patches/patch_SoD.conf | 2 +- utils/patches/patch_SoF.conf | 2 +- utils/patches/patch_UF.conf | 2 +- 6 files changed, 13 insertions(+), 4 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 3fe2430db..e9e7c5ef3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -36,6 +36,7 @@ static const uint32 MAX_MERC_GRADES = 10; static const uint32 MAX_MERC_STANCES = 10; static const uint32 BLOCKED_BUFF_COUNT = 20; static const uint32 QUESTREWARD_COUNT = 8; +static const uint32 ADVANCED_LORE_LENGTH = 8192; /* @@ -2966,6 +2967,12 @@ struct ItemViewRequest_Struct { /*046*/ char unknown046[2]; }; +struct ItemAdvancedLoreText_Struct { + int32 item_id; + char item_name[64]; + char advanced_lore[ADVANCED_LORE_LENGTH]; +}; + struct LDONItemViewRequest_Struct { uint32 item_id; uint8 unknown004[4]; diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 9467ab337..31b091ff8 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -331,7 +331,7 @@ OP_LDoNButton=0x596e OP_SetStartCity=0x7936 # Was 0x2d1b OP_VoiceMacroIn=0x202e OP_VoiceMacroOut=0x3920 -OP_ItemViewUnknown=0x0b64 +OP_ItemAdvancedLoreText=0x0b64 OP_VetRewardsAvaliable=0x05d9 OP_VetClaimRequest=0xcdde OP_VetClaimReply=0x361b diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index f410a3193..a39fde999 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -448,6 +448,8 @@ OP_FinishWindow2=0x40ef OP_ItemVerifyRequest=0x189c OP_ItemVerifyReply=0x097b +OP_ItemAdvancedLoreText=0x023b + # merchant stuff OP_ShopPlayerSell=0x791b OP_ShopRequest=0x4fed diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index d836c6360..619f986c1 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -327,7 +327,7 @@ OP_LDoNButton=0x41b5 # C OP_SetStartCity=0x7bf6 # C OP_VoiceMacroIn=0x31b1 # C OP_VoiceMacroOut=0x7880 # C -OP_ItemViewUnknown=0x21c7 # C +OP_ItemAdvancedLoreText=0x21c7 # C OP_VetRewardsAvaliable=0x4e4e # C OP_VetClaimRequest=0x771f # C OP_VetClaimReply=0x2f95 # C diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index a10715918..6a5d41fb4 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -576,7 +576,7 @@ OP_QueryResponseThing=0x0000 # # realityincarnate: these are just here to stop annoying several thousand byte packet dumps OP_LoginUnknown1=0x22cf OP_LoginUnknown2=0x43ba -OP_ItemViewUnknown=0x4db4 +OP_ItemAdvancedLoreText=0x4db4 #Petition Opcodes OP_PetitionSearch=0x0000 #search term for petition diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 71966dcbb..69d6bb1e5 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -336,7 +336,7 @@ OP_LDoNButton=0x1031 # C OP_SetStartCity=0x68f0 # C OP_VoiceMacroIn=0x1524 # C OP_VoiceMacroOut=0x1d99 # C -OP_ItemViewUnknown=0x4eb3 # C +OP_ItemAdvancedLoreText=0x4eb3 # C OP_VetRewardsAvaliable=0x0baa # C Mispelled? OP_VetClaimRequest=0x34f8 # C OP_VetClaimReply=0x6a5d # C