Entry 123
"The party's chat lines: ccAI::ChatMessage* and ChatMessageSender"
This entry answers the question left open by "The chat balloons: ccChatMsg, Mac Anu's players and Kite's calls".
Filescrates/piney-battle/src/party_chat.rscrates/piney-world/examples/evchar_probe.rscrates/piney-battle/src/party_ai.rscrates/piney-battle/src/ai_move.rscrates/piney-battle/src/event.rscrates/piney-battle/src/affect.rscrates/piney-battle/src/tables.rscrates/piney-battle/src/lib.rscrates/piney-battle/examples/battle_probe/party_ai.rscrates/piney-world/src/combat/chat.rscrates/piney-world/src/combat/mod.rscrates/piney-world/src/combat/stage.rscrates/piney-world/src/combat/town.rscrates/piney-world/src/town_party.rscrates/piney-world/src/party.rscrates/piney-world/src/field_world.rscrates/piney-world/src/ai.rscrates/piney-world/src/lib.rscrates/piney-game/src/area.rscrates/piney-game/src/world.rscrates/piney-game/src/session/tests/chat.rscrates/piney-game/src/session/event22.rstools/test_battle_chat_rs.pydocs/engine/battle.mddocs/engine/field-ui.mddocs/engine/field-game.md
120 drew the balloons, but the party still said nothing. The decisions
called Call::Chat, the runtime answered 0, and ChatMessageSender only
ran the arrival count down. These are ccAI::ChatMessage* (personal.cpp,
gcmn 0x00586130-0x00592a98): 57 functions over 77 tables of lines in
GCMN.PRG.
How a line is said
- Picked, not shown. A function picks its line and writes it into the
AI (+0x24, 80 bytes) through
ChatMessageModify, then setschatRequest. The member's nextChatMessageSender(the end ofBrains) opens it withccChatMsg::OpenChatand clears the request. - The template. Most functions check
partyFlag1 (no draw otherwise) and read the rowMessageIndex()(the character id; 18 for id 1 whilesaveData+0x220d is set, id 1's lines garbled). The tables hold one line per character, or three, chosen by(rand() >> 3) % 100(below 60, 90) or% 3. Nothing is said under manual control, but the draws are made first. ChatMessageModify.#0is the leader's name,#1a1 or the leader's,#aand#ba2 and a3 or " ". It stops at 79 bytes. Any other#code never advances, so the loop spins forever. Two lines have one: Orca's thirdfatalDamagedMessages("Oh #@&%!") and Rachel'scharmConfusionMessages("Oh %&*#,"). The port stops the copy there.- The specific ones.
AttackTargetreturns the kind it said (element 4, crowd 5, condition skills 6, level 1-3).AttackandDamagekeep their every-third counters, andAttributeGuardsets -3.Damage,NeutralandThanksHealfile or withdraw the "heal me" request (0x10016, in11 ((rand() >> 3) & 3)frames).ConditionModifysends 0x10012 again in 150. Rachel (id 12) compares weapon prices inNeutral, and Natsume (id 11) notes a member two levels up. Some lines turn the member (atan2f(d.x, -d.y)whenCheckAction(1)passes).Greetingonly points the AI. ChatMessageSender. Nothing once the party is wiped out. WhenarrivalChatCntreaches 0 out of a fight, the arrival's line is said:EnteredTown(the server'sarrive*Messages), orEnteredFieldfrom a town, or in a type-4 dungeon.
In the port
piney_battle::party_chat. It holdsChatTexts(the tables andgetAttributeStr's),modify,Ctx::chat_linefor every function,Ctx::chat_senderandCtx::greeting.- The stage's runtime. It answers
Call::ChatandCall::ChatMessageSenderwith them. The text goes out asShow::Chat(body, text). The area opens it over the member (handle1 << 24 | id), and the town does too (take_party_chats,handle(Kind::Spc, id)). - Lines the rules raise. These are
ChatAttack,ChatAttributeCritical,ChatDamage,ChatResurrectPlz,AffectMessagesandGreeting, and they were events nobody read.combat::chatnow runs them on the member's AI after the task that raised them: a member's frame, Kite's, the entry control's pass, the skills' pass, a trap, the boss. Those from menus and events run at the next frame's start.ChatDamageandAffectMessagesnow carry the HP before the hit, which is whatccFellow::Influenceholds when it calls them. ChangeEquipReport. In a field or dungeon the equipment order saysEquipOKorEquipNOT(FieldWorld::equip_report). The town's is not wired.levelOld. The AI constructor never sets it, and_ccMallocdoes not clear. The port had it at 0, so Piros said "Level... UP!" 30 frames into Mac Anu. It now starts at the character's level.
Checked
tools/test_battle_chat_rs.py(new). It runs the 45 entry points in eemu againstbattle_probe chat, 120 random worlds each (500 each withbulk 500). The worlds vary names, enemy skill lists, +0x220d,areaPrev, the server, the kept text and manual control. The kept text, every AI's fields, the bus, the bodies' flags and headings, the balloon opened and therand()count all match. Cases that pick a stray-#line hang the game'sChatMessageModifyand are drawn again. One case caught a name taken from no character (GratsLevelUp(NULL)). The game reads it through address 0, which is zero in eemu, so#1gives the leader's name. The port now passes no name there.party_chat::tests::modify_fills_the_codes. The codes, the 79-byte stop, and the stop at a stray code.session::tests::chat::a_member_speaks_in_a_fight. In event 3's east portal fight, Orca says two of his fight lines over his head whileinBattleis on.member_chat_shot(ignored) shows his balloon.session::event22::piros_says_his_arrival_line_in_mac_anu. Back in Mac Anu, Piros says his arrival line 151 frames in.- The workspace's tests, clippy and fmt pass. So do the party AI, fellow, Kite, navi, battle, enemy motion, party and event-character suites.
A Grunty's line (ccPGuso::main) is not this machinery. It calls
OpenChat itself with its own texts, so it is left.
levelOldin the game. What the heap holds there when a member is built in a town. The game may announce a level change on arrival. - The stray#lines. Whether they freeze a real console as they freeze eemu's run. - The order of raised lines. The game says them inside the hit, and the port says them after the task. Theirrand()draws fall later in the frame than the game's. -saveData+0x220d. What sets it (id 1's garbled lines).