package game import ( "fmt" "math/rand" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" "thehouseoficarus/internal/world" ) type assassinTaskEntry struct { MobID string MinLevel int MaxLevel int MinCount int MaxCount int Weight int } var assassinTaskTable = []assassinTaskEntry{ {"man", 1, 15, 10, 25, 8}, {"cow", 1, 15, 10, 25, 8}, {"slug", 1, 99, 15, 45, 15}, {"drone", 15, 99, 20, 50, 12}, {"crawler", 30, 99, 15, 40, 10}, {"phantom", 45, 99, 10, 30, 8}, } func (g *Game) assignAssassinTask(sess *net.Session, p *player.Player) { level := p.Level(player.Assassin) var eligible []assassinTaskEntry totalWeight := 0 for _, entry := range assassinTaskTable { if level >= entry.MinLevel && level <= entry.MaxLevel { eligible = append(eligible, entry) totalWeight += entry.Weight } } if len(eligible) == 0 { sess.WriteLine("The Client shakes their head. \"Nothing available for your level.\"") return } roll := rand.Intn(totalWeight) var chosen assassinTaskEntry for _, entry := range eligible { roll -= entry.Weight if roll < 0 { chosen = entry break } } count := chosen.MinCount + rand.Intn(chosen.MaxCount-chosen.MinCount+1) setPlayerFlag(p, "assassin_task_mob", chosen.MobID) setPlayerFlag(p, "assassin_task_total", count) setPlayerFlag(p, "assassin_task_remaining", count) g.AccountStore.SaveCharacter(p) def, err := g.MobStore.LoadDef(chosen.MobID) name := chosen.MobID if err == nil { name = def.Name } sess.WriteLine(g.colorize(sess, "assassin_task", fmt.Sprintf("\"Your target: %d %ss. Get to work.\"", count, name))) } func (g *Game) onAssassinKill(sess *net.Session, p *player.Player, mob *world.MobInstance) { taskMob := getPlayerFlagString(p, "assassin_task_mob") if taskMob == "" || taskMob != mob.DefID { return } remaining := getPlayerFlagInt(p, "assassin_task_remaining") if remaining <= 0 { return } xp := mob.MaxHP * 2 g.awardSkillXP(sess, p, player.Assassin, xp) if p.OptionBool("xp_drops") { sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp asm)", xp))) } remaining-- setPlayerFlag(p, "assassin_task_remaining", remaining) if remaining <= 0 { completed := getPlayerFlagInt(p, "assassin_tasks_completed") + 1 streak := getPlayerFlagInt(p, "assassin_streak") + 1 setPlayerFlag(p, "assassin_tasks_completed", completed) setPlayerFlag(p, "assassin_streak", streak) delete(p.Flags, "assassin_task_mob") setPlayerFlag(p, "assassin_task_remaining", 0) setPlayerFlag(p, "assassin_task_total", 0) rep := 1 bonus := streakBonus(streak) rep += bonus currentRep := getPlayerFlagInt(p, "assassin_reputation") setPlayerFlag(p, "assassin_reputation", currentRep+rep) sess.WriteLine(g.colorize(sess, "assassin_task", fmt.Sprintf("\n*** Assassin task complete! ***"))) if bonus > 0 { sess.WriteLine(g.colorize(sess, "assassin_task", fmt.Sprintf(" Streak bonus! %d tasks in a row. +%d bonus reputation.", streak, bonus))) } sess.WriteLine(g.colorize(sess, "assassin_task", fmt.Sprintf(" Reputation earned: %d (total: %d)", rep, currentRep+rep))) } else { total := getPlayerFlagInt(p, "assassin_task_total") def, _ := g.MobStore.LoadDef(taskMob) name := taskMob if def != nil { name = def.Name } sess.WriteLine(g.colorize(sess, "assassin_task", fmt.Sprintf(" Assassin task: %d of %d %ss remaining.", remaining, total, name))) } g.AccountStore.SaveCharacter(p) } func (g *Game) skipAssassinTask(sess *net.Session, p *player.Player) { rep := getPlayerFlagInt(p, "assassin_reputation") if rep < 30 { sess.WriteLine("You don't have enough Reputation to skip. (Need 30, have " + fmt.Sprint(rep) + ")") return } setPlayerFlag(p, "assassin_reputation", rep-30) delete(p.Flags, "assassin_task_mob") setPlayerFlag(p, "assassin_task_remaining", 0) setPlayerFlag(p, "assassin_task_total", 0) setPlayerFlag(p, "assassin_streak", 0) g.AccountStore.SaveCharacter(p) } func (g *Game) extendAssassinTask(sess *net.Session, p *player.Player) { rep := getPlayerFlagInt(p, "assassin_reputation") if rep < 30 { sess.WriteLine("You don't have enough Reputation to extend. (Need 30, have " + fmt.Sprint(rep) + ")") return } taskMob := getPlayerFlagString(p, "assassin_task_mob") if taskMob == "" { sess.WriteLine("You don't have an active task to extend.") return } setPlayerFlag(p, "assassin_reputation", rep-30) total := getPlayerFlagInt(p, "assassin_task_total") remaining := getPlayerFlagInt(p, "assassin_task_remaining") extension := total / 2 if extension < 5 { extension = 5 } setPlayerFlag(p, "assassin_task_total", total+extension) setPlayerFlag(p, "assassin_task_remaining", remaining+extension) g.AccountStore.SaveCharacter(p) def, _ := g.MobStore.LoadDef(taskMob) name := taskMob if def != nil { name = def.Name } sess.WriteLine(fmt.Sprintf("Task extended by %d. Kill %d more %ss (%d total).", extension, remaining+extension, name, total+extension)) } func streakBonus(streak int) int { if streak%1000 == 0 { return 50 } if streak%250 == 0 { return 35 } if streak%100 == 0 { return 25 } if streak%50 == 0 { return 15 } if streak%10 == 0 { return 5 } return 0 }