|
|
@@ -2,16 +2,9 @@ package health
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
- "log"
|
|
|
- "strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
|
|
|
- "wartank/server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/healthtime"
|
|
|
- "wartank/server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/isrepair"
|
|
|
- "wartank/server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/repairtime"
|
|
|
-
|
|
|
- // "wartank/pkg/components/sound"
|
|
|
"wartank/pkg/types"
|
|
|
)
|
|
|
|
|
|
@@ -22,33 +15,19 @@ import (
|
|
|
// Здоровье -- контроль здоровья танка
|
|
|
type Здоровье struct {
|
|
|
types.ИСражениеДействие
|
|
|
- время *healthtime.HealthTime // Изменяемое здоровье танка
|
|
|
- здоровПолн *healthtime.HealthTime // Полное здоровье танка
|
|
|
- здоровТекущ int // Старое доровье (до опроса)
|
|
|
- еслиНадоЛечить *isrepair.IsRepair // Необходимость восстановления
|
|
|
- времяДоЛеч *repairtime.RepairTime // Время до восстановления
|
|
|
- логин string // Для поиска контрольных строк
|
|
|
- канТик chan int // Канал для ровной отправки тиков
|
|
|
- уронСтарый int // Дельта урона здоровью за прошлый шаг
|
|
|
+ канТик chan int // Канал для ровной отправки тиков
|
|
|
+ счётЛечить int // Счётчик вызовов лечения
|
|
|
}
|
|
|
|
|
|
// НовЗдоровье -- возвращает новый *Здоровье
|
|
|
-func НовЗдоровье(действие types.ИСражениеДействие, логин string) (*Здоровье, error) {
|
|
|
+func НовЗдоровье(действие types.ИСражениеДействие) (*Здоровье, error) {
|
|
|
{ // Предусловия
|
|
|
if действие == nil {
|
|
|
return nil, fmt.Errorf("НовЗдоровье(): действие==nil")
|
|
|
}
|
|
|
- if логин == "" {
|
|
|
- return nil, fmt.Errorf("НовЗдоровье(): логин пустой")
|
|
|
- }
|
|
|
}
|
|
|
sf := &Здоровье{
|
|
|
ИСражениеДействие: действие,
|
|
|
- время: healthtime.NewHealthTime(),
|
|
|
- здоровПолн: healthtime.NewHealthTime(),
|
|
|
- еслиНадоЛечить: isrepair.NewIsRepair(),
|
|
|
- времяДоЛеч: repairtime.NewRepairTime(),
|
|
|
- логин: логин,
|
|
|
канТик: make(chan int, 2),
|
|
|
}
|
|
|
go sf.makeTik()
|
|
|
@@ -63,28 +42,14 @@ func (сам *Здоровье) makeTik() {
|
|
|
сам.Отменить()
|
|
|
// log._rintf("Здоровье.makeTick(): сражение завершёно\n")
|
|
|
}()
|
|
|
- countLow := 0
|
|
|
for {
|
|
|
select {
|
|
|
case <-сам.Кнт().Done():
|
|
|
return
|
|
|
default:
|
|
|
- if сам.ЕслиМёртвый() {
|
|
|
- return
|
|
|
- }
|
|
|
- switch сам.времяДоЛеч.Получ() <= 0 {
|
|
|
- case true:
|
|
|
- countLow++
|
|
|
- default:
|
|
|
- countLow = 0
|
|
|
- }
|
|
|
- if countLow > 90 {
|
|
|
- return
|
|
|
- }
|
|
|
+ сам.канТик <- 1
|
|
|
+ time.Sleep(time.Second * 10)
|
|
|
}
|
|
|
- сам.канТик <- 1
|
|
|
- time.Sleep(time.Second * 1)
|
|
|
- сам.времяДоЛеч.Dec()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -94,20 +59,13 @@ func (сам *Здоровье) пуск() {
|
|
|
сам.Отменить()
|
|
|
}()
|
|
|
for range сам.канТик {
|
|
|
- if err := сам.здоровьеНайти(); err != nil { // Найти свой здоровье
|
|
|
- log.Printf("Здоровье.run(): при попытке найти здоровье, err=\n\t%v\n", err)
|
|
|
- return
|
|
|
- }
|
|
|
- сам.времЛечитьНайти()
|
|
|
- if сам.еслиНадоЛечить.Get() {
|
|
|
- сам.лечить()
|
|
|
- }
|
|
|
+ сам.лечить()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Полное -- возвращает объект полного здоровья танка
|
|
|
func (сам *Здоровье) Полное() int {
|
|
|
- return сам.здоровПолн.Get()
|
|
|
+ return 0
|
|
|
}
|
|
|
|
|
|
// ЕслиМёртвый -- возвращает признак мертвичины танка
|
|
|
@@ -123,176 +81,22 @@ func (сам *Здоровье) ЕслиМёртвый() bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-// Ищет время восстановления ремки
|
|
|
-func (сам *Здоровье) времЛечитьНайти() {
|
|
|
- defer func() {
|
|
|
- if сам.времяДоЛеч.ЕслиМожно() {
|
|
|
- return
|
|
|
- }
|
|
|
- if сам.времяДоЛеч.ЕслиИзменилось() {
|
|
|
- log.Printf("Здоровье.findRepair(): до ремки=%v\n", сам.времяДоЛеч.Получ())
|
|
|
- }
|
|
|
- }()
|
|
|
- if сам.времяДоЛеч.ЕслиМожно() {
|
|
|
- return
|
|
|
- }
|
|
|
- var (
|
|
|
- strOut string
|
|
|
- lstBattle = сам.СписПолучить()
|
|
|
- isFind bool
|
|
|
- ind int
|
|
|
- )
|
|
|
- // <a href="pve?19-14.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>12 секунд</span></span></a>
|
|
|
- //
|
|
|
- for ind, strOut = range lstBattle {
|
|
|
- if !strings.Contains(strOut, `ILinkListener-currentControl-repairLink`) {
|
|
|
- continue
|
|
|
- }
|
|
|
- if strings.Contains(strOut, ` секунд</span></span></a>`) {
|
|
|
- isFind = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !isFind {
|
|
|
- return
|
|
|
- }
|
|
|
- strOut = lstBattle[ind]
|
|
|
- // <a href="pve?19-14.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>12 секунд</span></span></a>
|
|
|
- lstTime := strings.Split(strOut, `ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>`)
|
|
|
- if len(lstTime) < 2 {
|
|
|
- // log._rintf("ERRO Здоровье.findRepair(): при попытке получить ссылку на ремонт, strOut=\n%v\n", strOut)
|
|
|
- сам.Отменить()
|
|
|
- return
|
|
|
- }
|
|
|
- strTime := lstTime[1]
|
|
|
- lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
|
|
|
- strTime = lstTime[0]
|
|
|
- if err := сам.времяДоЛеч.Set(strTime); err != nil {
|
|
|
- // log._rintf("ERRO Здоровье.findRepair(): при установке времени восстановления ремки, err=\n\t%v\n", err)
|
|
|
- return
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// Восстановливает здоровье (~)
|
|
|
func (сам *Здоровье) лечить() {
|
|
|
- var (
|
|
|
- strOut string
|
|
|
- lstBattleOn = сам.СписПолучить()
|
|
|
- isFindRepair bool
|
|
|
- ind int
|
|
|
- )
|
|
|
+
|
|
|
// <span>Ремкомплект</span>
|
|
|
// <a href="pve?19-14.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>Ремкомплект</span></span></a>
|
|
|
- for ind, strOut = range lstBattleOn {
|
|
|
- if strings.Contains(strOut, `<span>Ремкомплект</span>`) {
|
|
|
- isFindRepair = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !isFindRepair {
|
|
|
- return
|
|
|
- }
|
|
|
- strOut = lstBattleOn[ind]
|
|
|
+
|
|
|
+ strLink := "https://wartank.ru/pve?19-{count}.ILinkListener-currentControl-repairLink"
|
|
|
// <a href="pve?6-26.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>Ремкомплект</span></span></a>
|
|
|
- lstLink := strings.Split(strOut, `<a href="`)
|
|
|
- strLink := lstLink[1]
|
|
|
- lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Ремкомплект</span></span></a>`)
|
|
|
- strLink = "https://wartank.ru/" + lstLink[0]
|
|
|
+ strLink = strings.ReplaceAll(strLink, "{count}", fmt.Sprint(сам.счётЛечить))
|
|
|
lstBattleOn, err := сам.Сеть().Get(strLink)
|
|
|
if err != nil {
|
|
|
// log._rintf("ERRO Здоровье.repair(): при выполнении GET-команды ремонта, err=\n\t%v\n", err)
|
|
|
- сам.Отменить()
|
|
|
return
|
|
|
}
|
|
|
if err = сам.СтрОбновить(lstBattleOn); err != nil {
|
|
|
// log._rintf("ERRO Здоровье.repair(): при обновлении lstBattle, err=\n\t%v\n", err)
|
|
|
return
|
|
|
}
|
|
|
- // sound.Repair()
|
|
|
- сам.уст(сам.здоровПолн.Get())
|
|
|
- // log._rintf("INFO Здоровье.repair(): здоровье восстановлено\n")
|
|
|
-}
|
|
|
-
|
|
|
-// Ищет своё здоровье (~)
|
|
|
-func (сам *Здоровье) здоровьеНайти() error {
|
|
|
- var (
|
|
|
- ind int
|
|
|
- strOut string
|
|
|
- isFind bool
|
|
|
- lstBattle = сам.СписПолучить()
|
|
|
- )
|
|
|
- if len(lstBattle) == 0 { // Принудительно обновим сражение
|
|
|
- if err := сам.Сеть().UpdateLst(); err != nil {
|
|
|
- сам.Отменить()
|
|
|
- return fmt.Errorf("Здоровье.здоровьеНайти(): пустой lstBattle, err=\n\t%w", err)
|
|
|
- }
|
|
|
- }
|
|
|
- for ind, strOut = range lstBattle {
|
|
|
- if strings.Contains(strOut, `alt="`+сам.логин+`"`) {
|
|
|
- isFind = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !isFind { // Свой танк не найден
|
|
|
- сам.Отменить()
|
|
|
- return fmt.Errorf("Здоровье.здоровьеНайти(): своё здоровье не найдено")
|
|
|
- }
|
|
|
- // Свой танк найден, ищем здоровье
|
|
|
- ind += 11
|
|
|
- strOut = lstBattle[ind]
|
|
|
- lstHealth := strings.Split(strOut, `<div class="value-block lh1"><span><span>`)
|
|
|
- strHealth := lstHealth[1]
|
|
|
- lstHealth = strings.Split(strHealth, `</span></span></div>`)
|
|
|
- strHealth = lstHealth[0]
|
|
|
- iHealth, err := strconv.Atoi(strHealth)
|
|
|
- if err != nil {
|
|
|
- сам.Отменить()
|
|
|
- return fmt.Errorf("Здоровье.здоровьеНайти(): здоровье(%v) не число, err=%w", strHealth, err)
|
|
|
- }
|
|
|
- сам.уст(iHealth)
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// уст -- устанавливает текущее здоровье
|
|
|
-func (сам *Здоровье) уст(знач int) {
|
|
|
- if знач <= 0 {
|
|
|
- // log._rintf("WARN Здоровье.уст(): кривое значение здоровья танка(%v)\n", val)
|
|
|
- знач = 0
|
|
|
- сам.Отменить()
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if знач > сам.здоровПолн.Get() {
|
|
|
- // log._rintf("WARN Здоровье.уст(): кривое текущее здоровье, %v/%v\n", val, sf.full.Get())
|
|
|
- сам.здоровПолн.Set(знач)
|
|
|
- сам.ВыстрелБлок().Reset()
|
|
|
- сам.еслиНадоЛечить.Reset()
|
|
|
- сам.здоровТекущ = знач
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- дельта := сам.здоровТекущ - знач
|
|
|
- if дельта > 0 { // Дельта будет больше нуля, если только было попадание в свой танк
|
|
|
- if дельта != сам.уронСтарый {
|
|
|
- // log._rintf("INFO Здоровье.уст(): потеря здоровья=%v/%v\n", -delta, val)
|
|
|
- сам.уронСтарый = дельта
|
|
|
- сам.здоровТекущ -= знач
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if знач <= 500 { // Запретить стрельбу
|
|
|
- сам.ВыстрелБлок().Set() // Установить запрет стрельбы пока слабое здоровье
|
|
|
- сам.еслиНадоЛечить.Set()
|
|
|
- // log._rintf("WARN Здоровье.setHealth(): низкий уровень здоровья(%v)\n", val)
|
|
|
- сам.МанёврНадоУст()
|
|
|
- return
|
|
|
- }
|
|
|
- // Разрешить стрельбу
|
|
|
- сам.ВыстрелБлок().Reset()
|
|
|
- сам.еслиНадоЛечить.Reset()
|
|
|
- if дельта > сам.здоровПолн.Get()*4/10 { // Проверить на критичность падения здоровья на 40%
|
|
|
- // log._rintf("WARN Здоровье.setHealth(): большая разовая потеря здоровья(%v)\n", delta)
|
|
|
- сам.МанёврНадоУст()
|
|
|
- return
|
|
|
- }
|
|
|
}
|