Fraud ScammingWriting conversations

Writing conversations

Change the victims, the scams and the written conversations, add your own, tune the AI and translate it all.

On this page

Everyone a player can text, what they answer, and what the AI that plays them is told, is in tr_fraud's dialogue folder. It stays readable when the script is escrowed, so you can rewrite it, translate it, or add your own people and scams.

FileWhat's in it
personalities.luaHow victims take a conversation, and the texts they give up and send their card with
victims.luaThe people in Messages' list, and their files
scams.luaWho the player can text as
conversations/A written conversation for each scam, for when the AI isn't used
ai.luaWhat the AI is told, what its scores are worth, and the few texts the script writes itself

The server checks all of it when it starts and prints any mistakes in the console. An error keeps off only what it breaks: one in a written conversation keeps that scam's written conversation off, one in ai.lua keeps the AI off, and any other keeps Messages from starting conversations until it's fixed.

The four values

Every victim has four hidden values, each from 0 to 100:

ValueMeaning
trustHow much they believe whoever is texting
suspicionHow sure they are it's a scam; at 100 they stop answering
angerHow fed up they are; at 100 they stop answering
patienceHow long they'll keep texting back; at 0 they stop answering

They start at the personality's start, plus its fit for the scam the player texts as. Every text then moves them, and the personality decides by how much: react scales what a text with each tag does to them, and drain comes off patience every text. When they give up, their last text is one of the personality's leave, for why.

The tags are authority, reassure, pressure, sympathy, flattery, greed, detail and ask.

A personality

The fields are listed at the top of personalities.lua. The two kinds of text every personality needs, in its own voice:

dialogue/personalities.lua
    leave = {
        anger = { 'There is no need to be rude. Please don\'t message me again.' },
        suspicion = { 'I don\'t think you are who you say you are. Goodbye.' },
        patience = { 'I\'m sorry, I have to go now. Goodbye.' },
    },
    reads = { 'Alright dear, here it is. {number}, it says {expiry}, and on the back {cvv}' },

Each can have as many texts as you like; one is picked at random. Every reads text needs all three of {number}, {expiry} and {cvv}, which the script fills in. leave can use the same words as a scam's cover and {cover} itself.

A scam

dialogue/scams.lua
Dialogue.scam('bank_security', {
    label = 'Bank card security',           -- what the player picks under "Text as"
    summary = 'One line about it.',         -- under the label
    cover = '{bank} card security',         -- who the player says they are, as the AI is told it
})

The id is what personalities' fit names, and the name of its file in conversations/. A scam without a written conversation can only be texted as while the AI is on (the server warns about it).

cover, and every text in a written conversation, can use {first}, {last}, {formal} (Mrs. Collins), {area}, {bank}, {relative} and {relation} (a family member of the victim's, like Tommy, their grandson).

A written conversation

One file per scam in conversations/, made of steps. At each step the victim says something, and the player picks one of its replies. Where a reply leads is the next step.

dialogue/conversations/delivery.lua
Dialogue.conversation('delivery', {
    start = 'start',
    steps = {
        start = {
            replies = {
                { 'GoPostal: we tried to deliver a parcel to you in {area} today. Reply to rebook.',
                    tags = { 'authority', 'detail' }, trust = 8, suspicion = 2, next = 'parcel' },
                { 'Hi, quick one: you have a parcel held at our depot.',
                    tags = { 'detail' }, trust = 5, suspicion = 4, next = 'parcel' },
            },
        },

        parcel = {
            say = {
                busy = 'A parcel? Ok, and?',
                grumpy = 'I didn\'t order anything.',
                default = 'Oh. What parcel?',
            },
            replies = { ... },
        },

        done = {
            say = { default = { 'Ok, one sec.', 'Alright, getting it.' } },
            ending = 'success',
        },

        no = {
            say = 'I\'ll sort it out myself, thanks. Bye.',
            ending = 'fail',
        },
    },
})

start is the first step. The player writes first, so it has no say: its replies are what the player can open with. Nothing can lead back to it.

say is the victim's text: one text, a list (one is picked at random), or a table that answers by who they are and how they feel. The first of these that is there is used:

  1. personality/mood, like ['anxious/angry']
  2. the personality: trusting, careful, hopeful, busy, lonely, anxious, proud, grumpy
  3. the mood: angry (anger 60 or more), suspicious (suspicion 60 or more), warm (trust 70 or more)
  4. default

replies are what the player can pick, one to four of them, shown in a fresh order every time. Each reply is:

  • its text, first, under 200 characters;
  • tags: up to two, which the personality's react scales by;
  • trust, suspicion, anger, patience: what it does to the four values (leave one out for 0; negative takes away);
  • next: where it leads.

next is a step, or a list of branches when it should depend on how the victim feels by then. The first branch whose min and max all hold is taken; the last has neither and takes everything else:

lua
next = {
    { go = 'reads', min = { trust = 50 }, max = { suspicion = 45 } },  -- trust 50 or more, suspicion 45 or less
    { go = 'why_fee' },
},

ending ends the conversation once the step's say is sent: 'success' and the victim sends their card right after, 'fail' and they're gone. An ending step has no replies, and every conversation needs at least one success. A victim can also give up at any step, when a reply takes anger or suspicion to 100 or patience to 0.

A victim's file

Opening someone in Messages shows their file: age, gender, where they live, their work, who they live with, their bank, a family member, how they are, and three or four things known about their life.

dialogue/victims.lua
victim('nora_dixon', 'Nora Dixon', 'Mrs.', 57, 'Morningwood', 'anxious', 'Pacific Standard', 'Kyle', 'son',
    'Worries about her son, who drives too fast.', {
        job = 'Receptionist at a dentist\'s',
        home = 'With her husband. Their son Kyle, 22, has his own place.',
        facts = {
            'Kyle drives a fast car far too fast, and she waits for a bad phone call every night.',
            'He has been in Mount Zonah once already after a crash.',
        },
    })
  • job, home and facts are shown as written (no placeholders). Write hints, not answers: things a scam could be built on, and things that would catch a lazy one out. The server warns when a line is too long for the screen.
  • The line on how they are is their personality's manner in personalities.lua.
  • Male or female goes by the title (Mr. is male).

The AI is told the same file: a text built on something true in it scores as convincing, and one that gets a fact wrong scores as fishy.

Tuning the AI

For every text the player sends, the AI writes the victim's next text and scores the player's:

Score0123
convincingEmpty, off the pointWeak or genericBelievableJust what this person needs to hear
rudePolite or neutralCurtInsultingAbuse or threats
fishyNothing oddA little offClearly wrongAn obvious scam

The victim sends their card when all of give holds and the player asks for it: enough texts, enough trust, little enough suspicion and anger, on a text that isn't itself clearly wrong or insulting. The script decides that, not the AI. When they aren't ready, the AI is told what holds them back and the victim says so: that is how a player learns what to do next.

What to change in ai.lua:

FieldWhat it's for
languageThe language victims write in, as you'd say it to the AI. As it ships they answer in whatever language the player writes
give, scores, tags, early, limitsHow hard victims are to win over
promptWho the AI is told it's playing and how. The answer's keys (say, tags, convincing, rude, fishy, gives) have to stay as they are
turn, mood, trust, patience, ready, notReadyThe note the AI gets with each text about how the victim feels right now
agrees, refusesTexts the script sends itself
breaksWords that mean the AI has stepped out of its part: an answer with one is thrown away and asked for again

Translating

The written conversations, the personalities' leave and reads, the victims' files and the scams' labels are all text a player reads: translate them in place. For the AI, also set language and translate agrees and refuses. The rest of the text players see is in locales/en.json.

Testing your changes

Restart the resource and read the server console: mistakes are printed there. Then text a few victims from a burner phone. To try a written conversation while you have a key, set texts.mode = 'written' in config.lua.

Was this page helpful?

Still stuck? Open a ticket on Discord.Privacy