polygon.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. package polygon
  2. import (
  3. "fmt"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "wartank/pkg/alias"
  9. "wartank/pkg/components/safe_int"
  10. "wartank/pkg/components/safe_string"
  11. "wartank/pkg/cons"
  12. "wartank/pkg/section"
  13. "wartank/pkg/types"
  14. "wartank/server/serv_bots/warbot/angar/base/polygon/polygonnet"
  15. "wartank/server/serv_bots/warbot/tank/tankstat/static_param"
  16. )
  17. /*
  18. Объект полигона на базе
  19. */
  20. const (
  21. времОжидПлат = "05:00" // Время ожидания платного ускорения
  22. времОжидБесплат = "30:00" // Время ожидания бесплатного ускорения
  23. стрПрочность = "прочность"
  24. стрТочность = "точность"
  25. стрБроня = "броня"
  26. стрАтака = "атака"
  27. )
  28. // Полигон -- объект полигона на базе
  29. type Полигон struct {
  30. *section.Секция
  31. бот types.ИБот
  32. танкСтат types.ИТанкСтат
  33. сеть *polygonnet.ПолигонСеть
  34. продуктСейчас *safe_string.БезопСтрока
  35. продуктКол *safe_int.БезопЦелое
  36. уровень *static_param.СтатПарам
  37. }
  38. // НовПолигон -- возвращает новый *Polygon
  39. func НовПолигон(база types.ИБаза) (*Полигон, error) {
  40. секция, ош := section.НовСекция(база.Бот(), "Полигон", `<title>Полигон</title>`)
  41. if ош != nil {
  42. return nil, fmt.Errorf("НовПолигон(): при создании ИСекция, ош=\n\t%w", ош)
  43. }
  44. уровень, ош := static_param.НовСтатПарам("уровень полигона")
  45. if ош != nil {
  46. return nil, fmt.Errorf("НовПолигон(): при создании уровня полигона, ош=\n\t%w", ош)
  47. }
  48. сам := &Полигон{
  49. Секция: секция,
  50. бот: база.Бот(),
  51. танкСтат: база.Бот().Танк().ТанкСтат(),
  52. продуктСейчас: safe_string.НовБезопСтрока(),
  53. продуктКол: safe_int.НовБезопЦелое(),
  54. уровень: уровень,
  55. }
  56. сам.сеть, ош = polygonnet.НовПолигонСеть(сам)
  57. if ош != nil {
  58. return nil, fmt.Errorf("NewPolygon(): in create NetPolygon, err=\n\t%w", ош)
  59. }
  60. _ = types.ИБазаПолигон(сам)
  61. return сам, nil
  62. }
  63. // Уровень -- возвращает уровень полигона
  64. func (сам *Полигон) Уровень() types.ИСтатПарам {
  65. return сам.уровень
  66. }
  67. // ПродуктКолСейчас -- количество продукта, что именно сейчас производится на полигоне
  68. func (сам *Полигон) ПродуктКолСейчас() int {
  69. return сам.продуктКол.Получ()
  70. }
  71. // ПродуктИмяСейчас -- что именно сейчас производится на полигоне
  72. func (сам *Полигон) ПродуктИмяСейчас() string {
  73. return сам.продуктСейчас.Получ()
  74. }
  75. // ПродуктВремяСейчас -- сколько осталось времени до обновы полигона
  76. func (сам *Полигон) ПродуктВремяСейчас() string {
  77. return сам.ВремяОстат().String()
  78. }
  79. // Пуск -- запускает работу полигона в отдельном потоке
  80. func (сам *Полигон) Пуск() error {
  81. go сам.пуск()
  82. return nil
  83. }
  84. const (
  85. стрАпгрейд = "апгрейд"
  86. )
  87. // выполняет опрос полигона базы.
  88. func (сам *Полигон) пуск() {
  89. сам.ОбратВремяУст("02")
  90. фнРабота := func() {
  91. defer time.Sleep(time.Minute * 20)
  92. сам.усилениеДобавить()
  93. сам.усилениеПровер()
  94. сам.времяОбнов()
  95. сам.построитьПровер()
  96. сам.проверитьУскорение()
  97. if сам.продуктСейчас.Получ() == стрАпгрейд {
  98. сам.ВремяОстат().Уст("00:10:00")
  99. }
  100. счёт := 5
  101. for счёт > 0 {
  102. if сам.уровеньПолучить() {
  103. break
  104. }
  105. счёт--
  106. }
  107. }
  108. for {
  109. select {
  110. case <-сам.Кнт().Done():
  111. return
  112. case <-сам.ВремяОстат().КаналСиг():
  113. фнРабота()
  114. default:
  115. фнРабота()
  116. }
  117. }
  118. }
  119. // Проверяет уровень полигона
  120. func (сам *Полигон) уровеньПолучить() bool {
  121. var (
  122. стрВых = ""
  123. еслиНидено bool
  124. )
  125. lstBase, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
  126. if err != nil {
  127. log.Printf("Полигон.уровеньПолучить(): при обновлении строк базы, err=\n\t%v\n", err)
  128. return false
  129. }
  130. // <span class="green2">Полигон - 5</span><br/>
  131. for _, стрВых = range lstBase {
  132. if strings.Contains(стрВых, `<span class="green2">Полигон - `) {
  133. еслиНидено = true
  134. break
  135. }
  136. }
  137. if !еслиНидено {
  138. return false
  139. }
  140. стрУровень := strings.TrimPrefix(стрВых, `<span class="green2">Полигон - `)
  141. стрУровень = strings.TrimSuffix(стрУровень, `</span><br/>`)
  142. цУров, ош := strconv.Atoi(стрУровень)
  143. if ош != nil {
  144. return false
  145. }
  146. сам.уровень.Уст(цУров)
  147. return true
  148. }
  149. // Проверяет на ускорение апгрейда полигона
  150. func (сам *Полигон) проверитьУскорение() {
  151. var (
  152. strOut = ""
  153. еслиНайдено bool
  154. )
  155. lstBase, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
  156. if err != nil {
  157. log.Printf("Полигон.проверитьУскорение(): при обновлении строк базы, err=\n\t%v\n", err)
  158. return
  159. }
  160. // Проверка на платное ускорение апгрейда + время
  161. { // Платное ускорение
  162. if strings.Contains(strOut, `Ускорить за`) {
  163. if err := сам.ОбратВремяУст(времОжидПлат); err != nil {
  164. log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидПлат, err)
  165. }
  166. сам.СценаРежим().РаботаУст(стрАпгрейд)
  167. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  168. сам.продуктСейчас.Уст(стрАпгрейд)
  169. сам.продуктКол.Уст(0)
  170. return
  171. }
  172. }
  173. { // Проверка на бесплатное ускорение апгрейда
  174. еслиНайдено = false
  175. for _, strOut = range lstBase {
  176. if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
  177. // Убедиться что есть строка платного ускорения
  178. еслиНайдено = true
  179. break
  180. }
  181. }
  182. if !еслиНайдено {
  183. return
  184. }
  185. if !strings.Contains(strOut, `>Ускорение<`) {
  186. return
  187. }
  188. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  189. сам.продуктСейчас.Уст(стрАпгрейд)
  190. сам.продуктКол.Уст(0)
  191. lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
  192. strLink := lstLink[1]
  193. lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
  194. strLink = "https://wartank.ru/" + lstLink[0]
  195. lstBase, err := сам.сеть.Get(strLink)
  196. if err != nil {
  197. // log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
  198. return
  199. }
  200. // sound.ArsenalForce()
  201. if err := сам.СтрОбновить(lstBase); err != nil {
  202. // log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
  203. return
  204. }
  205. сам.СценаРежим().РаботаУст(стрАпгрейд)
  206. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  207. сам.продуктКол.Уст(0)
  208. if err := сам.ОбратВремяУст(времОжидБесплат); err != nil {
  209. log.Printf("WARN Base.checkArsenalForce(): при установке бесплатного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидБесплат, err)
  210. }
  211. }
  212. // Все проверки прошли -- это просто работа
  213. сам.СценаРежим().РаботаУст("work")
  214. }
  215. // Проверяет необходимость постройки полигона
  216. func (сам *Полигон) построитьПровер() {
  217. фнПостроить := func() bool { // Поиск кнопки строительства
  218. // https://wartank.ru/building-upgrade/Polygon
  219. списПолигон, ош := сам.сеть.Клиент().Get("https://wartank.ru/building-upgrade/Polygon")
  220. if ош != nil {
  221. log.Printf("Полигон.построитьПровер(): при чтении страницы строительства полигона, ош=\n\t%v\n", ош)
  222. return false
  223. }
  224. стрСсылка := ""
  225. еслиНайти := false
  226. // <a class="simple-but border mb5" href="Polygon?66-1.ILinkListener-upgradeLink-link">
  227. for _, стрСсылка = range списПолигон {
  228. if strings.Contains(стрСсылка, `href="Polygon?`) {
  229. еслиНайти = true
  230. break
  231. }
  232. }
  233. if !еслиНайти { // Время полигона вышло
  234. return false
  235. }
  236. _ссылка := strings.TrimPrefix(стрСсылка, `<a class="simple-but border mb5" href="`)
  237. _ссылка = strings.TrimSuffix(_ссылка, `">`)
  238. ссылка := "https://wartank.ru/building-upgrade/" + _ссылка
  239. // https://wartank.ru/building-upgrade/Polygon?83-1.ILinkListener-upgradeLink-link
  240. списПолигон, ош = сам.сеть.Клиент().Get(ссылка)
  241. if ош != nil {
  242. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  243. return false
  244. }
  245. for _, стр := range списПолигон {
  246. if strings.Contains(стр, `href="Polygon?`) {
  247. return false
  248. }
  249. }
  250. { // подтверждение постройки
  251. // "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../wicket/page?13-1.ILinkListener-confirmLink\"><span><span>да, подтверждаю</span></span></a>"
  252. стрСсылка := ""
  253. еслиНайти := false
  254. for _, стрСсылка = range списПолигон {
  255. if strings.Contains(стрСсылка, `.ILinkListener-confirmLink`) {
  256. еслиНайти = true
  257. break
  258. }
  259. }
  260. if !еслиНайти { // Время полигона вышло
  261. return false
  262. }
  263. _ссылка := strings.TrimPrefix(стрСсылка, "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../")
  264. _ссылка = strings.TrimSuffix(_ссылка, "\"><span><span>да, подтверждаю</span></span></a>")
  265. ссылка := "https://wartank.ru/" + _ссылка
  266. // https://wartank.ru/wicket/page?135-1.ILinkListener-confirmLink
  267. _, ош = сам.сеть.Клиент().Get(ссылка)
  268. if ош != nil {
  269. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  270. return false
  271. }
  272. }
  273. return true
  274. }
  275. фнПостроить()
  276. log.Printf("Полигон.построитьПровер(): построен упешно\n")
  277. }
  278. // Обновляет оставшееся время полигона
  279. //
  280. // Этот объект сам описывает своё время
  281. func (сам *Полигон) времяОбнов() {
  282. var (
  283. strLastTime string
  284. еслиНайдено bool
  285. isSet bool
  286. lstPolygon = сам.СписПолучить()
  287. )
  288. defer func() {
  289. if !isSet {
  290. сам.ОбратВремяУст("05")
  291. }
  292. }()
  293. for _, lastTime := range lstPolygon {
  294. if strings.Contains(lastTime, `>Осталось: `) {
  295. strLastTime = lastTime
  296. еслиНайдено = true
  297. break
  298. }
  299. }
  300. if !еслиНайдено { // Время полигона вышло
  301. return
  302. }
  303. lstTime := strings.Split(strLastTime, `>Осталось: `)
  304. strLastTime = lstTime[1]
  305. lstTime = strings.Split(strLastTime, `</span>`)
  306. strLastTime = lstTime[0]
  307. if err := сам.Уст(alias.Время(strLastTime)); err != nil {
  308. // log._rintf("ERRO Polygon.updateTime(): при установке времени ожидания полигона(%v)\n\terr=%v\n", strLastTime, err)
  309. return
  310. }
  311. isSet = true
  312. }
  313. // Проверяет что именно активировано
  314. func (сам *Полигон) усилениеПровер() {
  315. var (
  316. еслиНайдено bool
  317. lstPolygon = сам.СписПолучить()
  318. ind = 0
  319. strOut string
  320. )
  321. for ind, strOut = range lstPolygon {
  322. if strings.Contains(strOut, `<span>Активно</span>`) {
  323. ind -= 9
  324. еслиНайдено = true
  325. break
  326. }
  327. }
  328. if !еслиНайдено {
  329. return
  330. }
  331. strOut = lstPolygon[ind]
  332. форсажИмя := ""
  333. switch { // Вычисляем контрольную строку
  334. case strings.Contains(strOut, `>улучшение точности<`):
  335. форсажИмя = стрТочность
  336. case strings.Contains(strOut, `>увеличение прочности<`):
  337. форсажИмя = стрПрочность
  338. case strings.Contains(strOut, `>усиление брони<`):
  339. форсажИмя = стрБроня
  340. case strings.Contains(strOut, `>усиление атаки<`):
  341. форсажИмя = стрАтака
  342. }
  343. // Вычислим на сколько
  344. strOut = lstPolygon[ind+1]
  345. lstOut := strings.Split(strOut, `<span class="green2">+`)
  346. strOut = lstOut[1]
  347. lstOut = strings.Split(strOut, ` на `)
  348. strOut = lstOut[0]
  349. iForce, err := strconv.Atoi(strOut)
  350. if err != nil {
  351. // log._rintf("NetPolygon.checkTime(): force(%v) not number, err=\n\t%v\n", strOut, err)
  352. return
  353. }
  354. сам.танкСтат.ФорсажОбнов(форсажИмя, iForce)
  355. сам.продуктСейчас.Уст("усиление-" + форсажИмя)
  356. сам.продуктКол.Уст(iForce)
  357. }
  358. // Выбирает самый слабый параметр и усиливает его
  359. func (сам *Полигон) усилениеДобавить() {
  360. if ош := сам.сеть.Обновить(); ош != nil {
  361. // log._rintf("Polygon.checkPolygon(): при принудительном обновлении lstPlygon, mode=%s\terr=\n\t%v\n", сам.ModeCurrent().Get(), err)
  362. сам.ОбратВремяУст("05")
  363. return
  364. }
  365. lstPoligon := сам.СписПолучить()
  366. if len(lstPoligon) == 0 {
  367. return
  368. }
  369. stat := сам.танкСтат
  370. iAttack := stat.Атака().Получ()
  371. iArmor := stat.Броня().Получ()
  372. iFyne := stat.Точность().Получ()
  373. iHard := stat.Прочность().Получ()
  374. strParam := стрАтака
  375. iParam := iHard
  376. {
  377. /*
  378. Вычислить самый слабый параметр.
  379. Политика вычислений:
  380. 1) hard -- прочность, самый низкоприоритетный параметр
  381. 2) armor -- броня, чуть лучше power
  382. 3) fyne -- точность, чуть лучше armor
  383. 4) attack -- атака, самый важный
  384. */
  385. if iArmor <= iParam {
  386. iParam = iArmor
  387. strParam = стрБроня
  388. }
  389. if iFyne <= iParam {
  390. iParam = iFyne
  391. strParam = стрТочность
  392. }
  393. if iAttack < iParam {
  394. strParam = стрАтака
  395. }
  396. }
  397. // Найти нужную строку активации
  398. var (
  399. ind int
  400. strOut string
  401. еслиНайдено bool
  402. )
  403. switch strParam {
  404. case стрАтака: // Усиливаем атаку
  405. for ind, strOut = range lstPoligon {
  406. if strings.Contains(strOut, `>усиление атаки<`) {
  407. еслиНайдено = true
  408. break
  409. }
  410. }
  411. if !еслиНайдено {
  412. return
  413. }
  414. ind += 8
  415. strOut = lstPoligon[ind]
  416. if strOut == "" {
  417. return
  418. }
  419. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  420. strOut = lstLink[1]
  421. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  422. strLink := "https://wartank.ru/" + lstLink[0]
  423. if _, err := сам.сеть.Get(strLink); err != nil {
  424. // log._rintf("ERRO NetPolygon.addForce(): in make request force attack, err=\n\t%v\n", err)
  425. return
  426. }
  427. { // Узнать на сколько форсирована атака
  428. strForce := lstPoligon[ind-7]
  429. lstForce := strings.Split(strForce, `<span class="green2">+`)
  430. strForce = lstForce[1]
  431. lstForce = strings.Split(strForce, ` на `)
  432. strForce = lstForce[0]
  433. iForce, err := strconv.Atoi(strForce)
  434. if err != nil {
  435. // log._rintf("ERRO NetPolygon.addForce(): strForceAttack(%v) not int, err=\n\t%v\n", strForce, err)
  436. return
  437. }
  438. сам.танкСтат.ФорсажОбнов("attack", iForce)
  439. сам.СценаРежим().РаботаУст(стрАтака)
  440. }
  441. case стрБроня: // Усиливаем броню
  442. еслиНайдено = false
  443. for ind, strOut = range lstPoligon {
  444. if strings.Contains(strOut, `>усиление брони<`) {
  445. еслиНайдено = true
  446. break
  447. }
  448. }
  449. if !еслиНайдено {
  450. return
  451. }
  452. ind += 8
  453. strOut = lstPoligon[ind]
  454. if strOut == "" {
  455. return
  456. }
  457. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  458. strOut = lstLink[1]
  459. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  460. strLink := "https://wartank.ru/" + lstLink[0]
  461. if _, err := сам.сеть.Get(strLink); err != nil {
  462. // log._rintf("NetPolygon.addForce(): in make request force armor, err=\n\t%v\n", err)
  463. return
  464. }
  465. { // Узнать на сколько форсирована броня
  466. strForce := lstPoligon[ind-7]
  467. lstForce := strings.Split(strForce, `<span class="green2">+`)
  468. strForce = lstForce[1]
  469. lstForce = strings.Split(strForce, ` на `)
  470. strForce = lstForce[0]
  471. iForce, err := strconv.Atoi(strForce)
  472. if err != nil {
  473. // log._rintf("ERRO NetPolygon.addForce(): strForceArmor(%v) not int, err=\n\t%v\n", strForce, err)
  474. return
  475. }
  476. сам.танкСтат.ФорсажОбнов(стрБроня, iForce)
  477. сам.СценаРежим().РаботаУст(стрБроня)
  478. }
  479. case стрТочность: // Усиливаем точность
  480. еслиНайдено = false
  481. for ind, strOut = range lstPoligon {
  482. if strings.Contains(strOut, `>улучшение точности<`) {
  483. еслиНайдено = true
  484. break
  485. }
  486. }
  487. if !еслиНайдено {
  488. return
  489. }
  490. ind += 8
  491. strOut = lstPoligon[ind]
  492. if strOut == "" {
  493. return
  494. }
  495. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  496. strOut = lstLink[1]
  497. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  498. strLink := "https://wartank.ru/" + lstLink[0]
  499. if _, err := сам.сеть.Get(strLink); err != nil {
  500. // log._rintf("ERRO NetPolygon.addForce(): in make request force fyne, err=\n\t%v\n", err)
  501. return
  502. }
  503. { // Узнать на сколько форсирована точность
  504. strForce := lstPoligon[ind-7]
  505. lstForce := strings.Split(strForce, `<span class="green2">+`)
  506. strForce = lstForce[1]
  507. lstForce = strings.Split(strForce, ` на `)
  508. strForce = lstForce[0]
  509. iForce, err := strconv.Atoi(strForce)
  510. if err != nil {
  511. // log._rintf("ERRO NetPolygon.addForce(): strForceFyne(%v) not int, err=\n\t%v\n", strForce, err)
  512. return
  513. }
  514. сам.танкСтат.ФорсажОбнов(стрТочность, iForce)
  515. сам.СценаРежим().РаботаУст(стрТочность)
  516. }
  517. case стрПрочность: // Усиливаем мощность
  518. еслиНайдено = false
  519. for ind, strOut = range lstPoligon {
  520. if strings.Contains(strOut, `>увеличение прочности<`) {
  521. еслиНайдено = true
  522. break
  523. }
  524. }
  525. if !еслиНайдено {
  526. return
  527. }
  528. ind += 8
  529. strOut = lstPoligon[ind]
  530. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  531. strOut = lstLink[1]
  532. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  533. strLink := "https://wartank.ru/" + lstLink[0]
  534. if _, err := сам.сеть.Get(strLink); err != nil {
  535. // log._rintf("NetPolygon.addForce(): in make request force hard, err=\n\t%v\n", err)
  536. return
  537. }
  538. { // Узнать на сколько форсирована прочность
  539. strForce := lstPoligon[ind-7]
  540. lstForce := strings.Split(strForce, `<span class="green2">+`)
  541. strForce = lstForce[1]
  542. lstForce = strings.Split(strForce, ` на `)
  543. strForce = lstForce[0]
  544. iForce, err := strconv.Atoi(strForce)
  545. if err != nil {
  546. // log._rintf("ERRO NetPolygon.addForce(): strForceHard(%v) not int, err=\n\t%v\n", strForce, err)
  547. return
  548. }
  549. сам.танкСтат.ФорсажОбнов(стрПрочность, iForce)
  550. сам.СценаРежим().РаботаУст(стрПрочность)
  551. }
  552. default: // Неизвестно что
  553. сам.СценаРежим().РаботаУст("неизвестно")
  554. // log._rintf("ERRO NetPolygon.addForce(): неизвестно что это, strParam=%q", strParam)
  555. return
  556. }
  557. }