Repository navigation
feat(bots): let the bots talk – template chat, party search, bot-to-bot conversations - #1438
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 825 |
| Duplication | 12 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
8b262dc to
aa7c923
Compare
Adds the "Bot chat" plugin (disabled by default). Bots announce opened Blood Castle, Devil Square and Chaos Castle entrances and started invasions with /post, comment on level milestones in the normal chat and answer whispers of players - with lines from the plugin configuration, no language model. A bot only posts about what it could do: an event only when it meets the entry requirements (BotMiniGameHandler.IsEligible), an invasion only when it may warp to the invaded map. A server-wide gap between posts, one announcement per event opening and per-bot cooldowns keep a large population from flooding the chat. Both post chances default to 0, and bots post only while the /post command is enabled. Lines are localized strings rendered per receiver, like the server announcements. The /post format is shared with PostChatCommandPlugIn.
A bot which posts "Blood Castle open, anyone going?" and keeps hunting
in another corner of the world can't be found. After its post it now
goes to a meeting point and waits there until the entrance closes:
next to the Messenger of Archangel (Blood Castle) or Charon (Devil
Square), found in the game data, or - since Chaos Castle is entered
with the ticket alone - in the safezone of its home town, which the
post names ({map}).
Waiting does not make the bot decline party invitations; a player who
invites it and enters takes it along like any party bot. The meeting
ends when the entrance closes, when a player takes the bot into a party
or when there is no route to the NPC.
A bot does not announce an event whose entrance closes in less than two
minutes, and a bot on an errand, on a revenge or in a party with a
player does not look for company.
A whisper reply line can now carry keywords - comma-separated words or phrases it answers, e.g. "how are you, how r u". The bot answers with a line whose keyword matches the whisper (whole words, ignoring case and punctuation, the longest match winning), and falls back to the replies without keywords when nothing matches. The default lines cover greetings, "how are you", the bot's level and map, party, thanks and goodbye. The bare "?" reply is replaced by "hi, what's up?".
When a player enters the game from the character selection (not after
a warp), the nearest bot which sees the player greets them in the
normal chat, e.g. "hi {player}, have a nice game". Without a bot in
sight nobody greets.
A player is greeted at most once per GreetingCooldown (30 minutes), so
logging out and in again doesn't start a round of greetings; the
chance is GreetingChancePercent (50 %), and the bot's own chat
cooldown applies.
A bot which accepts a player's party invitation thanks for it in the
party chat ("thx for invite"), and after an event the bot went through
with a player's party, one bot of that party says "gg". The chance is
PartyChatChancePercent (70 %); the bot's chat cooldown applies.
The accepted invitation is reported through the new
IBotPartyJoinedPlugIn plugin point, called by BotPartyHandler.
A bot killed by a player outside of an event says something about it in
the normal chat while it still lies there ("why??", "wtf {player}").
When the same player kills it again within the revenge memory - the
point at which the bot gives up its revenge - it says a resigned line
instead ("you again...").
The chance is KilledByPlayerChancePercent (70 %); the bot's chat
cooldown applies. OfflinePlayer exposes the recent death count per
killer for this.
When a player writes the name of a bot which sees them in the normal
chat ("Serael, how are you?"), the bot answers in the normal chat with
the same lines and keywords as a whisper reply. The name must be a
whole word; the whisper reply chance and cooldown apply.
Every SmallTalkInterval (10 minutes) per game server, with
SmallTalkChancePercent (50 %), a bot standing in a safezone says
something in the normal chat ("lf party {map}", "lag?"). Only a bot
which a player sees talks - talking to nobody would be wasted.
The lines are kept neutral on purpose: bots don't trade with players,
so they don't offer anything for sale. A forced start of the plugin
from the admin panel makes the small talk due at once.
Every default bot chat line now carries a Polish translation, so Polish
players see the bots talk in Polish without the server owner writing
the translations first. Event, map and item names stay English, as the
game data names them. The default reply keywords also understand
Polish whispers, with and without diacritics ("jak się masz",
"jak sie masz").
The bot chat configuration had one long "Lines" list in which every line named its situation. With some fifty lines, the admin panel showed one endless page, and a line could end up in the wrong situation or carry keywords which only whisper replies use. Every situation now has its own list (event lines, greetings, whisper replies, ...), each collapsible on its own in the plugin's configuration dialog. The lines only hold their text; the whisper replies keep their keywords. The situation enum is gone - the list a line is in says when it is said.
{map} names the map only, which is little help on a big map: a player asking
a bot "where are you?" still has to search for it. The new {location}
placeholder adds the bot's coordinates the way players write them, e.g.
"Devias 215, 40", so the mini map leads the way. The default "where are you"
replies use it.
In an event post, {location} is the meeting point next to the entry NPC; in an
invasion post, the invaded map alone.
A player looking for party members can now ask the bots the way players ask each other: "/post party 300-350 bk dw". A post with a party word and a level (a range, "300+", "min 300" or a single number) calls up to five free bots of the game server whose level fits; class words narrow it down, each meaning its whole class line (bk = Dark Knight, Blade Knight, Blade Master). The bots whisper to the player a few seconds apart, and the same search posted again calls five others. The player whispers back to a bot where to meet - "devias 215 40", a map name alone, or "here" - and the bot warps there, walks up and waits for the invitation, using the meeting of the event announcements. A map the bot may not go to it declines; a whisper without a place gets asked again. Map names are recognized in every translation. The /post command had no hook, and its messages go out as gens chat, so they can't be told apart from the gens chat in the chat-sent plugin point. A new plugin point reports the posts alone.
Up to now a bot only said a line on its own. Now two bots standing close
together talk like the townsfolk of a role-playing game: one says the opener
("my potions are running low"), the other answers a few seconds later ("the
shop here sells them cheap").
They only talk when a human player stands near them - nobody else would hear
it - and each player overhears about one conversation every five minutes; the
interval counts per player, so a quiet corner doesn't wait for a busy town.
Each conversation has a place: in a town (both bots in a safezone), out
hunting (both outside of it, usually fighting) or anywhere. Conversations are
drawn without repetition until all of a place were used.
The default configuration comes with seventy-three conversations, each with a
Polish translation; they live in a file of their own.
With the conversations, a bot no longer needs to talk to itself in town: "lf
party", "lag?" and the like are now said by two bots to each other. The lone
line of a bot standing in a safezone gets a new purpose instead - adverts like
those of a merchant ("selling potions, cheap! Lorencia 130, 125"), as the
groundwork for a merchant bot.
The adverts are off by default (chance 0) until such a bot exists; the
settings and the list are renamed after them.
Few things make an online world feel as alive as a stranger's "gz". When a
player levels up or makes a reset, the nearest bot which sees them now and then
congratulates them in the normal chat ("gz", "nice, 400!", "reset 12, nice
Hero").
The chance is 30 % and each player gets at most one congratulation per ten
minutes for each kind - with a high experience rate a player levels up every
minute. A reset logs the player out or not, depending on the reset
configuration, so it's noticed by the grown reset count when the bots look over
the players every few seconds.
A bot answered every whisper after the same random few seconds, whether it said "np" or a whole sentence - a pattern a player notices. Now the answer takes the time a player would need: a moment to read, then a little time per character, capped at twelve seconds. This applies to whisper and mention replies, the party chat, the party search whispers and the second line of a conversation.
A player who whispers "how are you?" twice and gets the very same "fine, thanks for asking" twice knows they talk to a machine. The bots now remember, per player and list, the line they said last and pick another one when the list has another to offer. This covers the lines said to one player: whisper and mention replies, greetings, congratulations, the comments on being killed and the party search questions.
A "good morning" at midnight gives a bot away. Every line and conversation now has a "When": anytime (the default), morning, day, evening or night, by the local time of the server, and a bot picks only among those which fit the hour. The defaults add a few: "good morning", "late night grind?", "still up?" - "the monsters don't sleep, neither do i". The hours are fixed; they only pick fitting lines, so configurable boundaries wouldn't be worth the extra settings.
A bot has no trade window and doesn't duel. A trade request to it went nowhere
without a word, and a duel challenge was never answered at all, which left the
challenger waiting. Now the bot refuses the duel like a player clicking "no",
and in both cases it often whispers why ("sry, no trade", "not now, maybe
later").
Two new plugin points report the requests: a trade request before it's
checked (a request to a bot can't be delivered), a duel challenge after it was
handed to the challenged player.
When a few players stand together and chat, a bot chiming in with a conversation or a "gz" drowns them out. Now a bot says nothing unasked - conversations, greetings, congratulations, merchant adverts, level and death comments - while the players near it are busy talking: three normal chat messages within 30 seconds by default, both configurable. Answers to a player who talks to the bot stay unaffected.
The editor of a translatable text showed a field for each language of the admin panel's own user interface only - English, German and Chinese. A server for Polish players could neither see nor edit the Polish translations: the Polish default lines of the bot chat were there, but invisible. The editor now also shows every language a text already has a translation in, and the additional content languages of the new AdminPanel:ContentLanguages setting (e.g. AdminPanel__ContentLanguages__0=pl), so a new text gets a field for them too. The admin panel itself isn't translated by this. The Docker images install icu-data-full as well: with the English culture data alone, which icu-libs brings on Alpine, the server doesn't know a culture like "pl", and a Polish player gets the English texts. This is required for the bots to answer Polish players in Polish, together with the player's account language set to "pl".
A list in a configuration form starts collapsed only when it holds more than ten items. The bot chat configuration has some twenty short lists, so most of them showed all their cards at once - one endless page instead of a list of sections to open one by one. A collection property can now be marked with [CollapsedByDefault] to start collapsed whatever its size; empty lists still show, so a first item can be created. The lists of the bot chat configuration use it.
A bot in a player's party ignored the party chat entirely: "~Karanwyn what level are you?" got no answer, although the same question as a whisper or in the normal chat did. The bot whose name a party message mentions now answers it in the party chat, with the whisper replies. Without a name, one bot of the party answers - but only a message which matches a keyword, so "ok" or "let's go" don't get a reply each time. A bot inside an event with the party answers as well.
"muszę kończyć" (I have to go) was answered with the fallback "sorry, busy
hunting": the default goodbye keywords knew only "bye", "nara", "pa" and the
like. They now cover the common English and Polish ways ("gtg", "gotta go",
"spadam", "muszę kończyć" with and without diacritics), with two more fitting
answers.
With three or four lines per situation and some eighty conversations, a player who spends an evening next to the bots hears them repeat themselves. The default configuration now has six to eight lines in most lists, 167 conversations (more for the town and for hunting, and more for the morning, day, evening and night), and the Polish translations read like a players' chat rather than a translation. The whisper replies understand more topics: the class, where to hunt, help, trade, and being asked whether it's a bot - which it answers with a wink, not a lie.
A bot answered in the language of the player's account, which is English
unless an admin set it: a Polish player who whispered "jak się masz?" got
"fine, thanks for asking". Now an answer to a message - whisper, mention,
party chat, the meeting place of a party search - is in the language the
message is written in, recognized by its typical words and letters. A
message which doesn't tell ("lol") is answered in the player's own language,
as before.
The words and letters per language are a list of the configuration; the
defaults know Polish and English.
A player who greets waves, a player who says "gz" claps - the game client has these emotes. A line or reply can now come with a gesture: the bot turns to the player it talks to and performs the client's emote animation, seen by the players around it. The default lines have fitting ones: a wave with a greeting and a goodbye, a clap with a congratulation, a cheer after an event, a victory pose at a level milestone, a raised fist when a player killed the bot and tears when it happens again. The gesture values are the client's animation numbers, so they're an enum rather than free numbers.
A conversation of two bots stopped after the reply, and a player standing
next to it who said something got no reaction - the bots carried on as if
nobody was there.
A conversation may now have a riposte, the first bot's last word ("guess who
failed +10 again" - "you?" - "me. again."); twenty-four such conversations join
the defaults, 194 in all. And a player who writes in the normal chat within
30 seconds after a conversation next to them gets an answer from one of the
two bots: a whisper reply when the message matches a keyword, otherwise one
of the new "player chimes in" lines ("right?", "haha, exactly").
The /post announcement of an event reaches the whole server, so it's rare (off by default). Now and then, a bot in a town where a player stands also reminds of an opened Blood Castle, Devil Square or Chaos Castle in the normal chat - "bc open, anyone going?" - heard only by the players around it. Like the post, only a bot which meets the event's entry requirements says it, and each town hears it once per opening; the chance is 50 % by default.
Players around a lucky drop or a golden monster say something - bots didn't.
Now the nearest bot sometimes comments on an excellent or ancient item a
player's kill dropped ("whoa, Excellent Dragon Armor!"), and a bot calls out
a notable monster which appeared near it while a player sees it ("Golden
Goblin here!"). The notable monsters are a configurable list of monster
numbers, by default the golden monsters, the Red Dragon and the White Wizard
of the invasions; an invasion spawning many of them gets one call-out per map
and monster in two minutes.
A bot greeted a player it had spent an hour with in a party like a
stranger. Now the bots remember their party companions (until the server
restarts): when such a player enters the game, an old companion nearby
greets first, with a line of its own ("hey Hero, together again?"), and the
same lines welcome the player who invites the bot again.
For staged scenes of an event - a bot telling of a dragon sighting before the invasion, a merchant bot advertising a GM's lottery - a game master can now make a bot say something: "/botsay <bot> <text>". The text is said as typed in the normal chat, to the players who see the bot. Only bots can be made to talk, never a player's character.
Wings are the milestone of a MU character, yet the bots let them pass in
silence - their own new pair as well as a player's.
- A bot which put on the wings it earned at a level milestone shows them off
("finally, my wings!") while a player sees it. The new plugin point
IBotWingsEarnedPlugIn reports the grant of BotWingHandler. At a level
milestone which brings wings, the bot talks about the wings, not the level.
- The nearest bot comments on the wings a player put on ("nice wings!") -
once per player and pair until the server restarts, since the wings go on
again after every change of equipment.
- The new placeholder {wings} names the bot's wings with their level ("Wings
of Soul +9"); the default whisper replies answer "what wings do you have?"
with it. A bot without wings answers with one of the new answers without
wings instead ("no wings yet, saving up").
One chance setting (50 %) for both comments; English and Polish default lines.
A player who invited a bot from Devias3 227 227 had it walk all the way from
the town of Devias, and "devias3" alone wasn't understood at all: the bot
only knew the names of the maps, and always entered a map through its spawn
gate. The floors of the Lost Tower and the Dungeon, and Kanturu Ruins 3,
aren't even connected by walkable ground to the spawn gate, so a bot which
was called there gave up on the way.
- The whisper may name a warp of the warp list ("devias3 227 227",
"losttower7"), in any of its translations. A map and a warp of the same
name ("Devias") still mean the map.
- With coordinates, the bot enters through the legal warp from which they
are the shortest walk - the same search the party followers use to reach
a leader on another floor, now shared. Blocked landing tiles are left out
there, as the town gates of Lorencia and Devias have some, and a player
who lands on one is moved to the spawn gate anyway.
- A warp named without coordinates: the bot waits at its gate.
- A bot already on the map, but farther away than the meeting's gate, warps
through the gate (at most twice) instead of walking.
- The level is checked for the warp which leads there, not for the map: a
level 60 bot doesn't promise to come to Lost Tower 7.
A party search like "/post party bc7" called no bot: the parser only knew
levels, and "bc7" holds no number of its own. Worse, "party bc 7" was read
as "level 7 and above".
A post may now name a Blood Castle, Devil Square or Chaos Castle with its
level ("bc7", "ds 5", "chaos castle 3"). Only bots which may enter that
event answer - checked by the same rules a bot follows its leader in with:
the event's level bracket (the lower one of the special characters
included) and the master class requirement, as configured for the event.
An event level which doesn't exist calls no bot, and the event's digit is
never taken for a character level. The words for the events are part of
the Bot chat configuration.
The paragraph about events in a party search ran past the line length of the docs (markdownlint MD013).
66f8b0f to
1fe7b43
Compare
sven-n
left a comment
There was a problem hiding this comment.
Code review (merge conflicts intentionally excluded; static analysis, tests not independently run).
Medium — Expired conversation entries retain bots indefinitely. src/GameLogic/Bots/BotChatThrottle.cs:401-433: RememberConversation appends to _recentConversations, but expiration cleanup occurs only when a player calls TakeRecentConversation. On quiet servers the list grows and holds strong references. Prune on insertion or periodically; test long-running conversations with no human replies.
Medium — Same-map meetings can be rejected. src/GameLogic/Bots/BotChatPlugIn.cs:727-755: FindMeetingEntry requires legal destination warps before checking whether the bot is already on the map and can walk to the requested location. Handle same-map reachable targets without requiring a warp; test maps with no warp entries.
Medium — Unreachable location discards the pending offer. BotChatPlugIn.cs:1092-1150: RemovePartyOffer(bot) runs before FindMeetingEntry succeeds. A player who supplies an unreachable place cannot correct it in the next whisper. Retain the offer until a valid meeting is accepted or it expires.
Medium — Competing party searches can reserve the same bot. BotChatPlugIn.cs:626-670 and BotChatThrottle.cs:176-221: candidate filtering and SetPartyOffer are not atomic across different requesters. Both players may receive an offer, but only the last is remembered. Introduce an atomic conditional reservation and concurrency test.
Low/medium — Delayed party reply can go to another party. BotChatPlugIn.cs:1155-1184 and BotChatSpeaker.cs:77-94: delayed response resolves bot.Party at send time. Capture and validate the original party/recipient before delivery.
Also consider expiring _occasions entries and cancellation of fire-and-forget RunLater actions on shutdown/config disable. The template-driven design and existing GM command permission check are positives.
|
Thanks for the review! All points are addressed in separate commits, each with a unit test:
Full test run is green. |
sven-n
left a comment
There was a problem hiding this comment.
LGTM. The bot chat is a feature plugin which is off by default (IDisabledByDefault), so existing servers are unaffected. The hooks into the core logic (trade and duel requests, /post, party join, wings) are only new plugin points. The texts the players see are localized resources, and the delayed lines are dropped as soon as the plugin is deactivated. The throttle state prunes expired occasions and conversations.
I built it and ran the tests locally on top of current master: everything passes, including all new bot chat tests. The only failure was ControllerCreatedAfterDisposalIsDisposedAsync, which is flaky on master as well.
Notes for later, none of them blocking:
- This is a large PR with several concerns: bot chat, content languages in the admin panel,
CollapsedByDefaultand the ICU data in the Dockerfiles. Smaller PRs would review faster. TradeRequestActioncallsITradeRequestedPlugInbefore the view plugin check, so a bot may reply to a trade request which then isn't sent. That's harmless, but worth moving after the check.BotChatPlugIn.cshas ~1600 lines. Splitting it by situation (whispers, party search, conversations) would help maintenance.
Generated by Claude Code
Summary
configurable lines, no language model: a few hundred bots must not cost more than a few string
replacements. The lines are localized texts; every player reads them in their own language.
/postand then wait at the event's NPCto be invited, answer whispers by keywords, greet, congratulate ("gz"), comment on being killed,
chat in the party, and talk to each other near a player like the townsfolk of an RPG.
/post party 300-350 bk dw– the bots whisper back, the player names the meeting place(
devias 215 40, a warp likedevias3orlosttower7, orhere), and the bot comes there to be invited.languages the panel itself isn't translated to (e.g. Polish), and lists which start
collapsed on request.
How to talk to the bots
📖 Full description: docs › Server-side AI bots › Talking
(part of this PR).
Enable Bot chat under Feature plugins (next to Bots). Then, as a player:
hi,how are you?,what level are you?,where are you?,party?,bye~) while it's in your party/post party 300-350 bk dw(also300+,min 300,pt,grupa, …) or an event:/post party bc7,pt ds 5devias 215 40,devias3 227 227,losttower7,lorencia, orherewhat wings do you have?/botsay <bot> <text>Polish players: set the account's Language Iso Code to
pl; to edit the Polish texts in thepanel, set
AdminPanel__ContentLanguages__0=pl(see Defaults).Commits
feat(bots): let bots talk with configurable lines– the plugin, posts about events/invasions, level milestonesfeat(bots): wait for players after announcing an eventfeat(bots): answer whispers by their keywordsfeat(bots): greet players entering the gamefeat(bots): talk in the party chat of a playerfeat(bots): comment on being killed by a playerfeat(bots): answer when mentioned in the normal chatfeat(bots): make small talk in townfeat(bots): ship the default chat lines in Polish toorefactor(bots): give every chat situation its own listfeat(bots): tell where the bot stands with {location}feat(bots): answer a player's party search posted with /postfeat(bots): let two bots talk to each other near a playerfeat(bots): turn the lone small talk into merchant advertsfeat(bots): congratulate players on level-ups and resetsfeat(bots): take the time to type an answerfeat(bots): don't give a player the same answer twice in a rowfeat(bots): fit lines and conversations to the time of dayfeat(bots): say why a trade or duel is turned downfeat(bots): keep quiet while the players around are talkingfeat(admin-panel): edit translations in the server's content languagesfeat(admin-panel): start the lists of the bot chat collapsedfeat(bots): answer in the party chatfeat(bots): understand more ways of saying goodbyefeat(bots): give the bots a richer default vocabularyfeat(bots): answer in the language of the player's messagefeat(bots): make gestures with the linesfeat(bots): let a conversation have a third line and players chime infeat(bots): remind of an opened event in townfeat(bots): react to rare drops and notable monsters nearbyfeat(bots): remember the players a bot was in a party withfeat(bots): let a game master make a bot talk with /botsayfeat(bots): comment on wingsfix(bots): come to a meeting place through the warp which leads therefeat(bots): understand an event in a party searchdocs(bots): wrap the party search paragraphfix(bots): forget bot conversations nobody chimed in tofix(bots): forget expired chat occasionsfix(bots): reserve a bot for one party search at a timefix(bots): keep the party offer when the meeting place is out of reachfix(bots): walk to a meeting place on the map the bot stands onfix(bots): say a delayed party line only to the party it was meant forfix(bots): drop delayed bot chat once the plugin is deactivateddocs(bots): describe naming another meeting place and walking on the same mapEach commit message explains its change; the sections below give the overview.
The plugin
BotChatPlugInis a feature plugin next to the Bots plugin, disabled by default(
IDisabledByDefault). Its configuration (BotChatConfiguration) has the chances, cooldowns andintervals at the top and one list per situation below: event lines, invasion lines, level
milestones, whisper replies (with keywords), greetings, party lines, congratulations, refusals,
party search whispers, class words, death comments, merchant adverts and conversations.
A list without lines keeps the bots silent in that situation.
Lines are
LocalizedStrings, rendered per receiver in their culture (like the serverannouncements), with placeholders:
{event},{map},{location}(map + coordinates, e.g."Devias 215, 40"),
{level},{class},{player},{resets},{partner},{wings}(e.g."Wings of Soul +9"; a bot without wings answers such a reply with "no wings yet, saving up"). Unknown placeholders
stay visible, so a typo in a configured line shows in the game. Bot messages bypass the
ChatMessageAction: they reach the human receivers only, never Discord or the chat bridge.What the bots say, and when
/post, then waits at the entry NPC (CC: in the home town's safezone) until the entrance closesBotMiniGameHandler.IsEligible); not when less than 2 minutes remain/post/post party 300+ bk)~)/botsay <bot> <text>Lines can come with a gesture – the client's emote animations (wave, clap, cheer, cry, ...),
performed facing the player; the defaults have fitting ones.
Keeping it believable and quiet
without repetition; filtered by place (town/hunting/anywhere) and time of day.
/postis enabled.(shop, buff, chaos machine trip, revenge) or in a player's party doesn't volunteer.
New plugin points and chat command
/botsay <bot> <text>(GM) – a bot says the text as typed; only bots.IBotPartyJoinedPlugIn– a bot accepted a player's party invitation.IBotWingsEarnedPlugIn– a bot put on the wings it earned at a level milestone (BotWingHandler).IPostMessageSentPlugIn– a player posted with/post. Posts go out as gens chat, so theexisting chat-sent plugin point can't tell them from the gens chat.
ITradeRequestedPlugIn– before a trade request is checked: a request to a bot can't bedelivered (no trade window), so it's reported early.
IDuelRequestedPlugIn– after a duel challenge was handed to the challenged player. A bot neveranswered one, which left the challenger waiting; the bot chat now refuses it.
Admin panel
LocalizedStringshowed fields only for the languages ofthe panel's own UI (en, de, zh-CN). It now also shows every language a text already has a
translation in, plus the languages of the new
AdminPanel:ContentLanguagessetting(e.g.
AdminPanel__ContentLanguages__0=pl), so a server for Polish players can edit Polish texts.[CollapsedByDefault]makes a collection start collapsed whatever its size(otherwise only lists of more than ten items do). The bot chat lists use it.
Startup,GameServer.Host,AdminPanel.Host) installicu-data-full:with the English-only culture data of Alpine's
icu-libs, the server doesn't know a culture likepl, and a player whose account language isplgets the English texts.Defaults
English lines with a Polish translation (the keywords understand Polish with and without
diacritics); 194 conversations, 24 of them with a riposte. For a Polish player to see them in Polish: the account's
Language Iso Code is
pl, the image has the full ICU data, and – to edit them – the contentlanguage setting.
Testing
typing time, repetition), the throttle (posts, occasions, cooldowns, conversation interval and
draw, reset detection, busy chat, party volunteers), the meeting planner and the greeter.
bot-behavior-update1(PR 1419) + these commits: all green(MUnique.OpenMU.Tests 2822 passed, Persistence.Initialization 808, Web 572, the rest green), no new
analyzer warnings. After the rebase onto the current
master(00f7373): all green –MUnique.OpenMU.Tests 2957 passed / 2 skipped, Persistence.Initialization 838 / 12 skipped, Web 661,
the rest green.
After the rebase onto
master3738d38: MUnique.OpenMU.Tests 2986 passed / 2 skipped,Persistence.Initialization 851 / 12 skipped, Web 666, the rest green.
Messenger of Archangel; whisper replies by keywords ("how are you?" → "fine, thanks for asking").
account whose language is
pl: Polish lines and Polish fields in the panel; party search with/post party 300+ bk(whispered offers, the next post calls other bots, the bot came to the namedplace and waited); "gz" on a level-up; trade and duel refusals; silence while players were
chatting; party chat answers and goodbyes; replies in the message's language; gestures;
conversations with a riposte and a player chiming in; the event reminder in town; rare drop and
golden monster reactions; greeting of an old party companion;
/botsay.replies; bot tests 338 passed, 9 failed - the Chaos Machine tests which fail on
mastertoo(fixed on
mastersince). In game, on a live server: a bot next to the playercongratulated on the wings the player put on.
devias3 227 227/losttower7,choosing the floor's warp of the Lost Tower, the level of that warp, a town gate with blocked
tiles, and the warp to another floor of the same map; bot tests 348 passed, 9 failed - the Chaos
Machine tests (fixed on
mastersince). A check on the Season 6 data showed which maps have parts that can't bewalked between: the 7 floors of the Lost Tower, the 3 parts of the Dungeon, and Kanturu Ruins 3.
In game, on a live server: whispering a warp as the meeting place (e.g.
devias3 227 227) broughtthe bot there through that warp.
bc7,bc 8,blood castle 7,ds5,cc3 350+,an unknown event level (
bc9) and a word which only ends in an event word (abc7). Full run on D:MUnique.OpenMU.Tests 2967 passed / 2 skipped, Persistence.Initialization 838 / 12 skipped, Web 661;
no new analyzer warnings. Not tested in game.
occasions, one reservation of a bot by 8 concurrent party searches, keeping the offer after an
unreachable place (and ending it with a reachable one), walking to coordinates on a map without a
warp entry, and a delayed party line which doesn't reach another party. Full run: MUnique.OpenMU.Tests 2992 passed / 2 skipped,
Persistence.Initialization 851 / 12 skipped, Web 666, the rest green; no new analyzer warnings.
Not tested in game.