Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Allow deltas for skill checks and in some other commands |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
89253a68b2a0bce108228be39ad126f8 |
User & Date: | murphy 2020-05-07 20:53:19.000 |
Context
2020-05-08
| ||
00:37 | Added spell slot management check-in: f75d632b0b user: murphy tags: trunk | |
2020-05-07
| ||
20:53 | Allow deltas for skill checks and in some other commands check-in: 89253a68b2 user: murphy tags: trunk | |
2020-05-06
| ||
11:24 | Replacing language placeholders: Merfolk -> Sylvan (Aquan), Vampire -> Infernal check-in: 706c71665d user: murphy tags: trunk | |
Changes
Changes to DragonDice.Bot/Session.fs.
︙ | ︙ | |||
54 55 56 57 58 59 60 | 0 Some (attr, delta) ) else None static let (|Skill|_|) s = | > > | > > > > > > > > > > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 0 Some (attr, delta) ) else None static let (|Skill|_|) s = let it = AbilityPattern.Match(s) if it.Success then Skill.tryParse it.Groups.[1].Value |> Option.bind (fun skill -> let delta = if it.Groups.[2].Success then int (it.Groups.[3].Value + it.Groups.[4].Value) else 0 Some (skill, delta) ) else None static let DifficultyPattern = Regex(@"^(?:dc|difficulty)\s+(.+)$", RegexOptions.CultureInvariant ||| RegexOptions.IgnoreCase) static let parsePassiveOption _ s = let it = DifficultyPattern.Match(s) if it.Success then Difficulty.ofString it.Groups.[1].Value else |
︙ | ︙ | |||
187 188 189 190 191 192 193 | /estimate <i>N</i>d<i>S</i> [+- <i>D</i>] — Estimate the result of rolling <i>N</i> <i>S</i>-sided dice and adding / subtracting <i>D</i> to / from the total. <b>Ability Checks:</b> /roll <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Roll a 20-sided die, add / subtract the ability modifier and <i>D</i>, and compare with <i>DC</i>. /estimate <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Estimate the result of rolling a 20-sided die, adding / subtracting the ability modifier and <i>D</i>, and comparing with <i>DC</i>. <b>Skill Checks:</b> | | > | < | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | /estimate <i>N</i>d<i>S</i> [+- <i>D</i>] — Estimate the result of rolling <i>N</i> <i>S</i>-sided dice and adding / subtracting <i>D</i> to / from the total. <b>Ability Checks:</b> /roll <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Roll a 20-sided die, add / subtract the ability modifier and <i>D</i>, and compare with <i>DC</i>. /estimate <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Estimate the result of rolling a 20-sided die, adding / subtracting the ability modifier and <i>D</i>, and comparing with <i>DC</i>. <b>Skill Checks:</b> /roll <i>SKILL</i> [+- <i>D</i>] [, <i>OPTION</i>] — Roll a 20-sided die, add / subtract the skill and ability modifiers and <i>D</i>, and compare with <i>DC</i>. /estimate <i>SKILL</i> [+- <i>D</i>] [, <i>OPTION</i>] — Estimate the result of rolling a 20-sided die, adding / subtracting the skill and ability modifiers and <i>D</i>, and comparing with <i>DC</i>. /passive <i>SKILL</i> [, <i>OPTION</i>] — Determine the passive score using the skill and ability modifiers, and compare with <i>DC</i>. /spellsave <i>SKILL</i> — Determine the spell save DC using the skill and ability modifiers of a magic skill. /proficiency — Determine the proficiency bonus of the active character. <b>Check Options:</b> dc|difficulty <i>DC</i> — The <i>DC</i> of an ability or skill check may be specified as a number or it may be one of the adjectives <i>Very Easy</i>, <i>Easy</i>, <i>Medium</i>, <i>Hard</i>, <i>Very Hard</i>, or <i>Impossible</i>. ins[piration] d<i>S</i> — An <i>S</i>-sided inspiration die may be added to a check. If multiple of these options are given, the highest <i>S</i> is used. adv[antage]|dis[advantage]|normal — Checks may be performed at advantage, disadvantage or normal conditions. If multiple of these options are specified, the majority of advantage or disadvantage options determines the conditions. |
︙ | ︙ | |||
324 325 326 327 328 329 330 | .Append(if result.IsSuccess then "Success" else "Failure") .Append("</b>") |> ignore else buffer.Append("<b>").Append(result.Score).Append("</b>") |> ignore return Markup (buffer.ToString(), List.empty) | | | | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | .Append(if result.IsSuccess then "Success" else "Failure") .Append("</b>") |> ignore else buffer.Append("<b>").Append(result.Score).Append("</b>") |> ignore return Markup (buffer.ToString(), List.empty) | "/roll" :: "?skill" :: Skill (skill, delta) :: opts | "/roll" :: Skill (skill, delta) :: opts -> let chr = selectedCharacter user let check = (chr.GetCheck(skill, 0) + delta, opts) ||> List.fold parseCheckOption let result = lock random (fun () -> Check.simulate random check) let buffer = Text.StringBuilder("<i>").Append(HttpUtility.HtmlEncode chr.Name).Append("</i> : ") .Append(Check.toDiceString check) if check.Difficulty > 0 then buffer.Append(" ≥ ").Append(check.Difficulty) |> ignore buffer.Append(" → ") |> ignore |
︙ | ︙ | |||
406 407 408 409 410 411 412 | plotCheckEstimates check, sprintf "<i>%s</i> : %s ∈ [%d, %d] → E = <b>%.2f</b>\nP[Critical] = <b>%.1f%%</b>\n" <| (HttpUtility.HtmlEncode chr.Name) <| (Check.toDiceString check) <| check.Minimum <| check.Maximum <| result.Score <| result.IsCritical * 100.0 ) | | | | | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | plotCheckEstimates check, sprintf "<i>%s</i> : %s ∈ [%d, %d] → E = <b>%.2f</b>\nP[Critical] = <b>%.1f%%</b>\n" <| (HttpUtility.HtmlEncode chr.Name) <| (Check.toDiceString check) <| check.Minimum <| check.Maximum <| result.Score <| result.IsCritical * 100.0 ) | "/estimate" :: "?skill" :: Skill (skill, delta) :: opts | "/estimate" :: Skill (skill, delta) :: opts -> let chr = selectedCharacter user let check = (chr.GetCheck(skill, 0) + delta, opts) ||> List.fold parseCheckOption if check.Difficulty > 0 then let result = Check.estimate check return Markup ( sprintf "<i>%s</i> : %s ∈ [%d, %d] ≥ %d → E = %.2f\nP[Critical] = <b>%.1f%%</b>\nP[Success] = <b>%.1f%%</b>\n" <| (HttpUtility.HtmlEncode chr.Name) <| (Check.toDiceString check) <| check.Minimum <| check.Maximum <| check.Difficulty <| result.Score <| result.IsCritical * 100.0 <| result.IsSuccess * 100.0, |
︙ | ︙ | |||
453 454 455 456 457 458 459 | None ) >> Seq.toList ) |> Seq.toList ) | | > | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | None ) >> Seq.toList ) |> Seq.toList ) | ["/spellsave"; skill] -> let chr = selectedCharacter user let skill = Skill.ofString skill let score = chr.GetSpellSave(skill) return Markup ( sprintf "<i>%s</i> : DC = <b>%d</b>" (HttpUtility.HtmlEncode chr.Name) score, List.empty ) | ["/proficiency"] -> |
︙ | ︙ | |||
1008 1009 1010 1011 1012 1013 1014 | for KeyValue (sense, v) in chr.Senses do if v > 0<ft> then if buffer.Length > pos then buffer.Append(", ") |> ignore buffer.Append(Sense.toString sense).Append(' ').Append(v).Append(" ft") |> ignore if buffer.Length = pos then buffer.Append("None") |> ignore return Markup (buffer.ToString(), List.empty) | | | | < | | 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 | for KeyValue (sense, v) in chr.Senses do if v > 0<ft> then if buffer.Length > pos then buffer.Append(", ") |> ignore buffer.Append(Sense.toString sense).Append(' ').Append(v).Append(" ft") |> ignore if buffer.Length = pos then buffer.Append("None") |> ignore return Markup (buffer.ToString(), List.empty) | ["/set"; Assignment (Skill (skill, delta), op, v)] -> let chr = selectedCharacter user let v = int v chr.Skills <- chr.Skills.With( match op with | '+' -> [skill, chr.Skills.[skill] + v] | '-' -> [skill, chr.Skills.[skill] - v] | _ -> [skill, v - delta] ) let buffer = Text.StringBuilder("<i>").Append(HttpUtility.HtmlEncode chr.Name).Append("</i> : ") let pos = buffer.Append("Skills = ").Length for KeyValue (skill, v) in chr.Skills do if v > 0 then let v = v + Ability.modifier chr.Abilities.[Skill.ability skill] if buffer.Length > pos then buffer.Append(", ") |> ignore buffer.Append(Skill.toString skill) .AppendFormat(CultureInfo.InvariantCulture, " {0:+0;-#}", v) |> ignore if buffer.Length = pos then buffer.Append("None") |> ignore return Markup (buffer.ToString(), List.empty) | ["/set"; Assignment (Ability (attr, delta), op, v)] -> let chr = selectedCharacter user let v = int v chr.Abilities <- chr.Abilities.With( match op with | '+' -> [attr, max 0 (chr.Abilities.[attr] + v)] | '-' -> [attr, max 0 (chr.Abilities.[attr] - v)] | _ -> [attr, max 0 (v - delta)] ) let buffer = Text.StringBuilder("<i>").Append(HttpUtility.HtmlEncode chr.Name).Append("</i> : ") let pos = buffer.Append("Abilities = ").Length for KeyValue (attr, v) in chr.Abilities do if buffer.Length > pos then buffer.Append(", ") |> ignore buffer.Append(Ability.toString attr) .AppendFormat(CultureInfo.InvariantCulture, " {0:D} ({1:+0;-#})", v, Ability.modifier v) |
︙ | ︙ |