Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
reworked shields: bashing, confusing and earth shields
Browse files Browse the repository at this point in the history
  • Loading branch information
anaseto committed Jun 9, 2018
1 parent a2afb68 commit d809eaf
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 56 deletions.
56 changes: 55 additions & 1 deletion combat.go
Expand Up @@ -100,7 +100,7 @@ func (g *game) AttackMonster(mons *monster, ev event) {
}
if RandInt(4) == 0 {
mons.EnterConfusion(g, ev)
g.PrintfStyled("Frundis glows… the %s appears confused.", logPlayerHit, mons.Kind)
g.PrintfStyled("Frundis glows… %s appears confused.", logPlayerHit, mons.Kind.Definite(false))
}
case g.Player.Weapon.Cleave():
var neighbors []position
Expand Down Expand Up @@ -345,3 +345,57 @@ func (g *game) ArmourClang() (sclang string) {
}
return sclang
}

func (g *game) BlockEffects(m *monster) {
switch g.Player.Shield {
case EarthShield:
dir := m.Pos.Dir(g.Player.Pos)
lat := g.Player.Pos.Laterals(dir)
for _, pos := range lat {
if !pos.valid() {
continue
}
if RandInt(4) == 0 && g.Dungeon.Cell(pos).T == WallCell {
g.Dungeon.SetCell(pos, FreeCell)
g.Stats.Digs++
g.MakeNoise(WallNoise, pos)
g.Fog(pos, 1, g.Ev)
}
}
case BashingShield:
if m.Kind == MonsSatowalgaPlant || m.Pos.Distance(g.Player.Pos) > 1 {
break
}
if RandInt(3) == 0 {
break
}
dir := m.Pos.Dir(g.Player.Pos)
pos := m.Pos
for i := 0; i < 3; i++ {
npos := pos.To(dir)
if !npos.valid() || g.Dungeon.Cell(npos).T == WallCell {
break
}
mons := g.MonsterAt(npos)
if mons.Exists() {
break
}
pos = npos
}
if !m.Status(MonsExhausted) {
m.Statuses[MonsExhausted] = 1
g.PushEvent(&monsterEvent{ERank: g.Ev.Rank() + 100 + RandInt(50), NMons: m.Index, EAction: MonsExhaustionEnd})
}
if pos != m.Pos {
m.MoveTo(g, pos)
}
case ConfusingShield:
if m.Pos.Distance(g.Player.Pos) > 1 {
break
}
if RandInt(4) == 0 {
m.EnterConfusion(g, g.Ev)
g.Printf("%s appears confused.", m.Kind.Definite(true))
}
}
}
107 changes: 70 additions & 37 deletions game.go
Expand Up @@ -318,6 +318,7 @@ func (g *game) InitPlayer() {
//g.Player.Weapon = DancingRapier
//g.Player.Weapon = Sabre
//g.Player.Weapon = HarKarGauntlets
//g.Player.Shield = EarthShield
}

func (g *game) InitLevel() {
Expand Down Expand Up @@ -356,17 +357,9 @@ func (g *game) InitLevel() {

// Equipment
g.Equipables = make(map[position]equipable)
for eq, data := range EquipablesRepartitionData {
if _, ok := eq.(weapon); ok {
continue
}
if _, ok := eq.(armour); ok {
continue
}
g.GenEquip(eq, data)
}
g.GenWeapon()
g.GenArmour()
g.GenShield()

// Rods
g.Rods = map[position]rod{}
Expand Down Expand Up @@ -545,6 +538,73 @@ func (g *game) SeenGoodArmour() (count int) {
return count
}

func (g *game) SeenGoodShield() (count int) {
for eq, b := range g.GeneratedEquipables {
sh, ok := eq.(shield)
if ok && b && sh != Buckler {
count++
}
}
return count
}

func (g *game) GenShield() {
ars := [4]shield{Buckler, ConfusingShield, BashingShield, EarthShield}
n := 11 + 5*g.SeenGoodShield()
if g.SeenGoodShield() == 2 {
return
}
if g.SeenGoodShield() == 0 {
n -= 2 * g.Depth
if n < 2 {
if g.Depth < 6 {
n = 2
} else {
n = 1
}
}
} else if g.SeenGoodShield() == 1 {
n -= 4 * (g.Depth - 7)
if n < 2 {
if g.Depth < 12 {
n = 2
} else {
n = 1
}
}
} else if g.Player.Shield != NoShield && g.Player.Shield != Buckler {
n += 10
} else if g.Depth > WinDepth {
n = 2
}
r := RandInt(n)
if r != 0 {
if !g.GeneratedEquipables[Buckler] && (g.Depth > 0 && RandInt(2) == 0 || g.Depth > 3) {
pos := g.FreeCellForStatic()
g.Equipables[pos] = Buckler
g.GeneratedEquipables[Buckler] = true
}
return
}
loop:
for {
for i := 0; i < len(ars); i++ {
if g.GeneratedEquipables[ars[i]] {
// do not generate duplicates
continue
}
n := 50
r := RandInt(n)
if r == 0 {
pos := g.FreeCellForStatic()
g.Equipables[pos] = ars[i]
g.GeneratedEquipables[ars[i]] = true
break loop
}
}
}
}

func (g *game) GenArmour() {
ars := [7]armour{Robe, LeatherArmour, ChainMail, PonderousnessPlates, SpeedRobe, CelmistRobe, HarmonistRobe}
n := 11 + 5*g.SeenGoodArmour()
Expand Down Expand Up @@ -576,7 +636,7 @@ func (g *game) GenArmour() {
}
r := RandInt(n)
if r != 0 {
if !g.GeneratedEquipables[LeatherArmour] && (RandInt(2) == 0 || g.Depth > 3) {
if !g.GeneratedEquipables[LeatherArmour] && (RandInt(2) == 0 || g.Depth >= 3) {
pos := g.FreeCellForStatic()
g.Equipables[pos] = LeatherArmour
g.GeneratedEquipables[LeatherArmour] = true
Expand All @@ -602,7 +662,6 @@ loop:
break loop
}
}

}
}

Expand Down Expand Up @@ -665,32 +724,6 @@ loop:
}
}

func (g *game) GenEquip(eq equipable, data equipableData) {
depthAdjust := data.minDepth - g.Depth
var r int
if depthAdjust >= 0 {
r = RandInt(data.rarity * (depthAdjust + 1) * (depthAdjust + 1))
} else {
switch eq.(type) {
case shield:
if !g.GeneratedEquipables[eq] {
r = data.FavorableRoll(-depthAdjust)
} else {
r = RandInt(data.rarity * 2)
}
default:
// not reached
return
}
}
if r == 0 {
pos := g.FreeCellForStatic()
g.Equipables[pos] = eq
g.GeneratedEquipables[eq] = true
}

}

func (g *game) FrundisInLevel() bool {
for _, eq := range g.Equipables {
if wp, ok := eq.(weapon); ok && wp == Frundis {
Expand Down
43 changes: 25 additions & 18 deletions items.go
Expand Up @@ -806,7 +806,9 @@ type shield int
const (
NoShield shield = iota
Buckler
Shield
ConfusingShield
EarthShield
BashingShield
)

func (sh shield) Equip(g *game) {
Expand All @@ -829,8 +831,12 @@ func (sh shield) String() (text string) {
switch sh {
case Buckler:
text = "buckler"
case Shield:
text = "shield"
case ConfusingShield:
text = "confusing shield"
case EarthShield:
text = "earth shield"
case BashingShield:
text = "bashing shield"
}
return text
}
Expand All @@ -839,18 +845,26 @@ func (sh shield) Short() (text string) {
switch sh {
case Buckler:
text = "Bk"
case Shield:
text = "Sh"
case ConfusingShield:
text = "Cn"
case EarthShield:
text = "Er"
case BashingShield:
text = "Bs"
}
return text
}

func (sh shield) Desc() (text string) {
switch sh {
case Buckler:
text = "A buckler is a small shield that can block attacks. You cannot use it if you are wielding a two-handed weapon."
case Shield:
text = "A shield can block attacks. You cannot use it if you are wielding a two-handed weapon."
text = "A buckler is a small shield that can block attacks. (incompatible with two-handed weapon)"
case ConfusingShield:
text = "A confusing shield blocks attacks, sometimes confusing monsters. (incompatible with two-handed weapon)"
case EarthShield:
text = "An earth shield offers great protection, but impact sound can disintegrate nearby walls. (incompatible with two-handed weapon)"
case BashingShield:
text = "A bashing shield can block attacks and push ennemies away. (incompatible with two-handed weapon)"
}
return text
}
Expand All @@ -863,8 +877,10 @@ func (sh shield) Block() (block int) {
switch sh {
case Buckler:
block += 6
case Shield:
case ConfusingShield, BashingShield:
block += 9
case EarthShield:
block += 15
}
return block
}
Expand All @@ -885,12 +901,3 @@ func (data equipableData) FavorableRoll(lateness int) int {
}
return r
}

var EquipablesRepartitionData = map[equipable]equipableData{
//Robe: {5, 0},
//LeatherArmour: {5, 0},
//ChainMail: {10, 3},
//PlateArmour: {15, 6},
Buckler: {10, 2},
Shield: {15, 5},
}
4 changes: 4 additions & 0 deletions monster.go
Expand Up @@ -899,6 +899,7 @@ func (m *monster) HitPlayer(g *game, ev event) {
if m.Blocked(g) {
g.Printf("Clang! You block %s's attack.", m.Kind.Definite(false))
g.MakeNoise(ShieldBlockNoise, g.Player.Pos)
g.BlockEffects(m)
return
}
if g.Player.HasStatus(StatusSwap) && !g.Player.HasStatus(StatusLignification) {
Expand Down Expand Up @@ -1042,6 +1043,7 @@ func (m *monster) TormentBolt(g *game, ev event) bool {
m.InflictDamage(g, damage, 15)
} else {
g.Printf("You block the %s's bolt of torment.", m.Kind)
g.BlockEffects(m)
g.ui.MonsterProjectileAnimation(g, g.Ray(m.Pos), '*', ColorCyan)
}
m.Statuses[MonsExhausted] = 1
Expand Down Expand Up @@ -1104,6 +1106,7 @@ func (m *monster) ThrowRock(g *game, ev event) bool {
} else if block {
g.Printf("You block %s's rock. Clang!", m.Kind.Indefinite(false))
g.MakeNoise(ShieldBlockNoise, g.Player.Pos)
g.BlockEffects(m)
g.ui.MonsterProjectileAnimation(g, g.Ray(m.Pos), '●', ColorMagenta)
ray := g.Ray(m.Pos)
if len(ray) > 0 {
Expand Down Expand Up @@ -1154,6 +1157,7 @@ func (m *monster) ThrowJavelin(g *game, ev event) bool {
if RandInt(3) == 0 {
g.Printf("You block %s's %s. Clang!", m.Kind.Indefinite(false), "javelin")
g.MakeNoise(ShieldBlockNoise, g.Player.Pos)
g.BlockEffects(m)
g.ui.MonsterJavelinAnimation(g, g.Ray(m.Pos), false)
} else if !g.Player.HasStatus(StatusDisabledShield) {
g.Player.Statuses[StatusDisabledShield] = 1
Expand Down
24 changes: 24 additions & 0 deletions pos.go
Expand Up @@ -263,3 +263,27 @@ func (pos position) idx() int {
func (pos position) valid() bool {
return pos.Y >= 0 && pos.Y < DungeonHeight && pos.X >= 0 && pos.X < DungeonWidth
}

func (pos position) Laterals(dir direction) []position {
switch dir {
case E, ENE, ESE:
return []position{pos.NE(), pos.SE()}
case NE:
return []position{pos.E(), pos.N()}
case N, NNE, NNW:
return []position{pos.NW(), pos.NE()}
case NW:
return []position{pos.W(), pos.N()}
case W, WNW, WSW:
return []position{pos.SW(), pos.NW()}
case SW:
return []position{pos.W(), pos.S()}
case S, SSW, SSE:
return []position{pos.SW(), pos.SE()}
case SE:
return []position{pos.S(), pos.E()}
default:
// should not happen
return []position{}
}
}

0 comments on commit d809eaf

Please sign in to comment.