Advertisement
Guest User

globalmap_group.fos

a guest
Nov 12th, 2015
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.15 KB | None | 0 0
  1. //
  2. // FOnline: 2238
  3. // Rotators
  4. //
  5. // globalmap_group.fos
  6. //
  7.  
  8. #include "_macros.fos"
  9. #include "follower_h.fos"
  10. #include "logging_h.fos"
  11. #include "MSGSTR.h"
  12. #include "npc_common_h.fos"
  13. #include "tracking.fos"
  14. #include "worldmap_h.fos"
  15.  
  16. import uint GetGlobalMapRelief(uint x, uint y) from "worldmap";
  17. import void FindEncounter(array<Critter@>& group, Item@ car, uint x, uint y, uint& encounterDescriptor, bool& waitForAnswer, bool empty) from "worldmap";
  18. import void InviteToEncounter(array<Critter@>& group, Item@ car, uint encounterDescriptor, int combatMode, uint& mapId, uint16& hexX, uint16& hexY, uint8& dir) from "worldmap";
  19. import array<Critter@> WorldmapGetPlayers(uint zx, uint zy) from "worldmap_players";
  20. import void WorldmapUpdateGroup(array<Critter@>& group) from "worldmap_players";
  21. import void WorldmapUpdatePlayer(Critter@ player) from "worldmap_players";
  22. import void WorldmapRemovePlayer(Critter@ player) from "worldmap_players";
  23. import void CarMessage(Critter@ cr, Item@ car, int msg) from "car";
  24.  
  25. //import void WMIdle(Critter& cr) from "sleepiness";
  26. //import void WMEnterIdle(Critter& cr) from "sleepiness";
  27. //import void WMNotIdle(Critter& cr) from "sleepiness";
  28. //import void DecumulateSleepiness(Critter& cr) from "sleepiness";
  29. //import void SendCombatZones(Critter& cr) from "sleepiness";
  30.  
  31.  
  32. funcdef void FGlobalProcessFunc(int processType, Critter& cr, Item@ car, float& curX, float& curY, float& toX, float& toY, float& speed, uint& encounterDescriptor, bool& waitForAnswer);
  33.  
  34. array<FGlobalProcessFunc@> GlobalProcessFunctions =
  35. {
  36. GlobalProcessMove,
  37. GlobalProcessEnter,
  38. GlobalProcessStartFast,
  39. GlobalProcessStart,
  40. GlobalProcessSetMove,
  41. GlobalProcessStopped,
  42. GlobalProcessNpcIdle,
  43. GlobalProcessKick,
  44. };
  45.  
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////
  47. // Output:
  48. // Critter& cr - who called this function, in most times is leader of group;
  49. // x,y - current position;
  50. // toX, toY - destination position;
  51. // speed - speed of group, must set in GLOBAL_PROCESS_SET_MOVE; also you can type -1 to stop group;
  52. // if encounterDescriptor != 0 than global_invite calls;
  53. // if waitForAnswer == false than global_invite calls after this function, else call after leader confirm invite;
  54. // Call types see in Global map events in _defines.fos
  55. void global_process(int processType, Critter& cr, Item@ car,
  56. float& curX, float& curY, float& toX, float& toY, float& speed,
  57. uint& encounterDescriptor, bool& waitForAnswer)
  58. {
  59. // Main processing is done here
  60. FGlobalProcessFunc@ func = GlobalProcessFunctions[processType];
  61. func(processType, cr, car, curX, curY, toX, toY, speed, encounterDescriptor, waitForAnswer);
  62.  
  63. // Process sleepiness
  64. switch(processType)
  65. {
  66. case GLOBAL_PROCESS_MOVE:
  67. case GLOBAL_PROCESS_SET_MOVE:
  68. {
  69. //if(speed != 0)
  70. //WMNotIdle(cr);
  71. break;
  72. }
  73. case GLOBAL_PROCESS_ENTER:
  74. {
  75. //WMNotIdle(cr);
  76. break;
  77. }
  78. case GLOBAL_PROCESS_START_FAST:
  79. {
  80. //WMEnterIdle(cr);
  81. break;
  82. }
  83. case GLOBAL_PROCESS_STOPPED:
  84. case GLOBAL_PROCESS_KICK:
  85. {
  86. //WMIdle(cr);
  87. break;
  88. }
  89. case GLOBAL_PROCESS_NPC_IDLE:
  90. {
  91. //DecumulateSleepiness(cr);
  92. break;
  93. }
  94. default:
  95. }
  96. }
  97.  
  98.  
  99. void GlobalProcessMove(int processType, Critter& cr, Item@ car,
  100. float& curX, float& curY, float& toX, float& toY, float& speed,
  101. uint& encounterDescriptor, bool& waitForAnswer)
  102. {
  103. MoveGlobalGroup(cr, car, curX, curY, toX, toY, speed);
  104. int curXi = int(curX);
  105. int curYi = int(curY);
  106. int oldXi = curXi;
  107. int oldYi = curYi;
  108.  
  109. if(++cr.GlobalMapMoveCounter % (__EncounterTime / __GlobalMapMoveTime) == 0)
  110. {
  111. array<Critter@>@ group = cr.GetGlobalGroup();
  112. Critter@ leader = group[0];
  113. int groupIgnore = 0;
  114. for(uint c = 1, g = group.length(); c < g; c++)
  115. {
  116. if(group[c].IsPlayer() && group[c].GetAccess() >= ACCESS_TESTER)
  117. groupIgnore++;
  118. }
  119.  
  120. // Validate charisma
  121. if((speed > 0.1f && int(group.length() - groupIgnore) > int(leader.Stat[ST_CHARISMA] < 3 ? 3 : leader.Stat[ST_CHARISMA] + leader.Perk[PE_MAGNETIC_PERSONALITY])) && (not valid(car)))
  122. {
  123. leader.SayMsg(SAY_NETMSG, TEXTMSG_GAME, STR_CRIT_BAD_CHARISMA);
  124. speed = 0.0f; // Stop
  125. return;
  126. }
  127.  
  128. // admin info
  129. if(leader.IsPlayer() && leader.GetAccess() == ACCESS_ADMIN)
  130. leader.Say(SAY_NETMSG, "Players in zone: " + WorldmapGetPlayers(oldXi / ZONE_LENGTH, oldYi / ZONE_LENGTH).length());
  131.  
  132. // update zone players information
  133. WorldmapUpdateGroup(group);
  134.  
  135. if(GetGlobalMapRelief(curXi, curYi) != 0 /* && GetVisibleLocations(curXi, curYi, 0, cr, null) == 0*/)
  136. {
  137. FindEncounter(group, car, curXi, curYi, encounterDescriptor, waitForAnswer, false);
  138. #ifdef __DEBUG__
  139. FLog(LOG_WMLOCATIONS, "TICK " + curXi + " " + curYi);
  140. #endif
  141. }
  142. }
  143.  
  144. //SendCombatZones(cr);
  145. Critter@[]@ group = cr.GetGlobalGroup();
  146. uint players=0;
  147. for (uint i=0; i<group.length(); i++)
  148. {
  149. if(group[i].IsPlayer())
  150. {
  151. group[i].AddScore(SCORE_SCAUT, 1);
  152. players++;
  153. }
  154.  
  155. }
  156. if(players>1 && cr.IsPlayer()) cr.AddScore(SCORE_DRIVER, players-1);
  157.  
  158. }
  159.  
  160. void GlobalProcessEnter(int processType, Critter& cr, Item@ car,
  161. float& curX, float& curY, float& toX, float& toY, float& speed,
  162. uint& encounterDescriptor, bool& waitForAnswer)
  163. {
  164. array<Critter@>@ group = cr.GetGlobalGroup();
  165. int movementType = (valid(car) ? car.Proto.Car_MovementType : GM_WALK_GROUND);
  166. int curXi = int(curX);
  167. int curYi = int(curY);
  168.  
  169. if(movementType == GM_WALK_WATER && GetGlobalMapRelief(curXi, curYi) == 0)
  170. {
  171. // Find land
  172. bool landFounded = false;
  173. const int maxx = __GlobalMapWidth * __GlobalMapZoneLength;
  174. const int maxy = __GlobalMapHeight * __GlobalMapZoneLength;
  175. for(int ox = -1; ox <= 1; ox++)
  176. {
  177. for(int oy = -1; oy <= 1; oy++)
  178. {
  179. int xx = curXi + ox;
  180. int yy = curYi + oy;
  181. if(xx >= 0 && xx < maxx && yy >= 0 && yy < maxy && GetGlobalMapRelief(xx, yy) != 0)
  182. {
  183. FindEncounter(cr.GetGlobalGroup(), car, xx, yy, encounterDescriptor, waitForAnswer, true);
  184. ox = oy = 2; // Exit from loop
  185. landFounded = true;
  186. }
  187. }
  188. }
  189.  
  190. if(!landFounded)
  191. FindEncounter(cr.GetGlobalGroup(), car, curXi, curYi, encounterDescriptor, waitForAnswer, true);
  192. }
  193. else
  194. {
  195. FindEncounter(cr.GetGlobalGroup(), car, curXi, curYi, encounterDescriptor, waitForAnswer, true);
  196. }
  197. }
  198.  
  199. void GlobalProcessStartFast(int processType, Critter& cr, Item@ car,
  200. float& curX, float& curY, float& toX, float& toY, float& speed,
  201. uint& encounterDescriptor, bool& waitForAnswer)
  202. {
  203. array<Critter@>@ group = cr.GetGlobalGroup();
  204.  
  205. int curZoneX = int(curX) / __GlobalMapZoneLength;
  206. int curZoneY = int(curY) / __GlobalMapZoneLength;
  207. ScanZone(group, curZoneX, curZoneY);
  208.  
  209. // update zone players information
  210. WorldmapUpdateGroup(group);
  211. }
  212.  
  213. void GlobalProcessStart(int processType, Critter& cr, Item@ car,
  214. float& curX, float& curY, float& toX, float& toY, float& speed,
  215. uint& encounterDescriptor, bool& waitForAnswer)
  216. {
  217. // NOOB ANTI-RAPE PROTECTION
  218. array<Critter@>@ group = cr.GetGlobalGroup();
  219. //cr.Say(SAY_NETMSG, "Group length: " + group.length());
  220. bool strangers = false;
  221. if(group.length>1)
  222. {
  223. for(uint i = 0; i < group.length(); i++)
  224. {
  225. if(cr.IsPlayer() && group[i].IsPlayer() && ((GetGroupIndex(cr)!=GetGroupIndex(group[i])) || GetGroupIndex(cr)<200 || GetGroupIndex(group[i])<200)) strangers=true;
  226. //cr.Say(SAY_NETMSG, "My group index: " + GetGroupIndex(cr) + " Other group index: " + GetGroupIndex(group[i]));
  227. }
  228. if(strangers)
  229. {
  230. cr.Say(SAY_NETMSG, "|4291317840 You are being followed by strangers. Be careful: check your party and kick them if necessary.");
  231. cr.PlaySound("encoalert.ogg", true);
  232. }
  233. }
  234. }
  235.  
  236. void GlobalProcessSetMove(int processType, Critter& cr, Item@ car,
  237. float& curX, float& curY, float& toX, float& toY, float& speed,
  238. uint& encounterDescriptor, bool& waitForAnswer)
  239. {
  240. array<Critter@>@ group = cr.GetGlobalGroup();
  241. Critter@ leader = group[0];
  242. int curXi = int(curX);
  243. int curYi = int(curY);
  244. int toXi = int(toX);
  245. int toYi = int(toY);
  246.  
  247. // admin info
  248. if(leader.IsPlayer() && leader.GetAccess() == ACCESS_ADMIN)
  249. leader.Say(SAY_NETMSG, "Players in target zone: " + WorldmapGetPlayers(toXi / ZONE_LENGTH, toYi / ZONE_LENGTH).length());
  250.  
  251. // automatically cancel tracking
  252. LooseTrack(leader, true);
  253.  
  254. if((int(group.length()) > int(leader.Stat[ST_CHARISMA] < 3 ? 3 : leader.Stat[ST_CHARISMA] + leader.Perk[PE_MAGNETIC_PERSONALITY])) && (not valid(car)))
  255. {
  256. leader.SayMsg(SAY_NETMSG, TEXTMSG_GAME, STR_CRIT_BAD_CHARISMA);
  257. return;
  258. }
  259.  
  260. speed = GLOBAL_MAP_BASE_SPEED;
  261. if(valid(car))
  262. {
  263. uint strNum = 0;
  264. if(group.length() > car.Proto.Car_CrittersCapacity)
  265. strNum = STR_CAR_CRIT_OVERLOAD;
  266. else if(car.Charge == 0)
  267. strNum = STR_CAR_FUEL_EMPTY;
  268. else if(car.Deterioration >= _CarGetMaxDeterioration(car))
  269. strNum = STR_CAR_BROKEN;
  270. if(strNum != 0)
  271. {
  272. // if(GetLvar(cr, LVAR_wm_idle)==0)
  273. CarMessage(leader, car, strNum);
  274. speed = 0;
  275. return;
  276. }
  277.  
  278. speed = car.Proto.Car_Speed * GLOBAL_MAP_BASE_SPEED / 10.0f;
  279.  
  280. // Find near water for boats
  281. // In radius of one zone (left, top, right, bottom)
  282. if(car.Proto.Car_MovementType == GM_WALK_WATER)
  283. {
  284. if(GetGlobalMapRelief(curXi, curYi) != 0)
  285. {
  286. const int maxx = __GlobalMapWidth * __GlobalMapZoneLength;
  287. const int maxy = __GlobalMapHeight * __GlobalMapZoneLength;
  288. const int[] ox = { -1, 0, 1, 0 };
  289. const int[] oy = { 0, -1, 0, 1 };
  290. for(int i = 1, ii = __GlobalMapZoneLength; i <= ii; i++)
  291. {
  292. for(int j = 0; j < 4; j++)
  293. {
  294. int xx = curXi + ox[j] * i;
  295. int yy = curYi + oy[j] * i;
  296. if(xx >= 0 && xx < maxx && yy >= 0 && yy < maxy && GetGlobalMapRelief(xx, yy) == 0)
  297. {
  298. curX = float(xx);
  299. curY = float(yy);
  300. // Exit from loop
  301. j = 4;
  302. i = ii;
  303. }
  304. }
  305. }
  306. }
  307. }
  308. }
  309. else
  310. {
  311. // Pathfinder perk bonus
  312. speed = (speed * (100 + cr.Perk[PE_PATHFINDER] * 25)) / 100; // 12-07-2013 Cubik: zmiana z 15 na 25% dla perka pathfinder
  313. if(cr.IsPlayer() && cr.GetAccess() >= ACCESS_TESTER)
  314. speed += float(GetLvar(cr, LVAR_extra_speed)) / 1000.0f;
  315. speed += float(cr.Skill[SK_OUTDOORSMAN]) / 100.f; // up to 50% bonus
  316. speed*=1.3; // 12-07-2013 Cubik: zwiekszenie o 30% szybkosci poruszania sie na piechote
  317. }
  318. }
  319.  
  320. void GlobalProcessStopped(int processType, Critter& cr, Item@ car,
  321. float& curX, float& curY, float& toX, float& toY, float& speed,
  322. uint& encounterDescriptor, bool& waitForAnswer)
  323. {
  324. array<Critter@>@ group = cr.GetGlobalGroup();
  325. Critter@ leader = group[0];
  326.  
  327. // update zone players information
  328. WorldmapUpdateGroup(group);
  329.  
  330. toX = curX;
  331. toY = curY;
  332. speed = -1;
  333. }
  334.  
  335. void GlobalProcessNpcIdle(int processType, Critter& cr, Item@ car,
  336. float& curX, float& curY, float& toX, float& toY, float& speed,
  337. uint& encounterDescriptor, bool& waitForAnswer)
  338. {
  339. // Critter& cr - is npc who call idle
  340. // Process npc group on global map
  341.  
  342. if(curX == toX && curY == toY) // Stopped
  343. {
  344. if(_IsFollower(cr))
  345. {
  346. if(ELAPSED_TIME - uint(cr.FollowerVar[FV_WM_NEXT_TRY]) > REAL_SECOND(10))
  347. cr.FollowerVarBase[FV_WM_NEXT_TRY] = ELAPSED_TIME;
  348. else
  349. return;
  350.  
  351. if(cr.FollowerVarBase[FV_WM_IDLE] == 0)
  352. cr.FollowerVarBase[FV_WM_IDLE] = ELAPSED_TIME;
  353.  
  354. if((ELAPSED_TIME - uint(cr.FollowerVar[FV_WM_IDLE])) > FOLLOWER_WM_GARBAGE_TIME)
  355. {
  356. Log("Garbaging follower " + cr.Id + ", PID=" + cr.GetProtoId() + ", master:" + cr.FollowerVar[FV_MASTER]);
  357. FLog(LOG_FOLLOWER, "Garbaging follower " + cr.Id + ", PID=" + cr.GetProtoId() + ", master:" + cr.FollowerVar[FV_MASTER]);
  358. DeleteNpc(cr);
  359. }
  360.  
  361. if(valid(cr.GetGlobalGroup()))
  362. {
  363. array<Critter@> members;
  364. members = cr.GetGlobalGroup();
  365. for(uint i = 0; i < members.length(); i++)
  366. if(int(members[i].Id) == cr.FollowerVar[FV_MASTER])
  367. {
  368. return;
  369. }
  370. RejoinMaster(cr, true);
  371. }
  372. else
  373. RejoinMaster(cr, true);
  374.  
  375. }
  376. // if you want enter to location under group than type
  377. // encounterDescriptor=uint(-1);
  378. // waitForAnswer=false;
  379. }
  380. }
  381.  
  382. void GlobalProcessKick(int processType, Critter& cr, Item@ car,
  383. float& curX, float& curY, float& toX, float& toY, float& speed,
  384. uint& encounterDescriptor, bool& waitForAnswer)
  385. {
  386. int curXi = int(curX);
  387. int curYi = int(curY);
  388. if(GetGlobalMapRelief(curXi, curYi) == 0)
  389. {
  390. // Say to leader
  391. array<Critter@>@ group = cr.GetGlobalGroup();
  392. group[0].SayMsg(SAY_NETMSG, TEXTMSG_GAME, STR_CANT_KICK_ON_WATER);
  393. return;
  394. }
  395.  
  396. cr.LeaveGlobalGroup();
  397. }
  398.  
  399.  
  400.  
  401. void RejoinMaster(Critter& cr, bool TeleportToMap)
  402. {
  403. Critter@ master = GetCritter(cr.FollowerVar[FV_MASTER]);
  404. if(valid(master))
  405. {
  406. if(master.GetMapId() == 0)
  407. {
  408. cr.LeaveGlobalGroup();
  409. TransferToNPCMap(cr); // Because otherwise: FOServer::SScriptFunc::Crit_TransitToGlobalGroup : Script error: Critter already on global.
  410. cr.TransitToGlobalGroup(master.Id); // ... when calling this function
  411. cr.FollowerVarBase[FV_WM_IDLE] = 0;
  412. UNSETFLAG(cr.FollowerVarBase[FV_FLAGS], FV_FLAG_FLED_BATTLE);
  413. }
  414. else if(TeleportToMap && !FLAG(cr.FollowerVarBase[FV_FLAGS], FV_FLAG_FLED_BATTLE))
  415. {
  416. cr.TransitToMap(master.GetMapId(), master.HexX, master.HexY, cr.Dir);
  417. cr.FollowerVarBase[FV_WM_IDLE] = 0;
  418. }
  419. }
  420. }
  421.  
  422. //
  423. // Asks player that just enter global if he wants to track nearby available groups
  424. //
  425. uint e_AskAboutAvailable(array<uint>@ values)
  426. {
  427. Critter@ leader = GetCritter(values[0]);
  428. if(valid(leader))
  429. AskAboutAvailable(leader);
  430. // never ask again
  431. return 0;
  432. }
  433.  
  434. ////////////////////////////////////////////////////////////////////////////////////////////////////
  435. // Call on invite to encaunter.
  436. // If mapId != 0 than group enter to it.
  437. void global_invite(Critter& leader, Item@ car, uint encounterDescriptor, int combatMode, uint& mapId, uint16& hexX, uint16& hexY, uint8& dir)
  438. {
  439. array<Critter@>@ group = leader.GetGlobalGroup();
  440. // manage coordinates of trackers and tracked
  441. SetTrackingCoords(group, group[0].WorldX, group[0].WorldY);
  442. // cancel tracking mode (because of encounter)
  443. LooseTrack(group[0], false);
  444.  
  445. if(encounterDescriptor == uint(-1))
  446. {
  447. array<Location@> locations;
  448. if(GetLocations(leader.WorldX, leader.WorldY, 0, locations) != 0)
  449. {
  450. Location@ loc = locations[0];
  451. Map@ map = loc.GetMapByIndex(0);
  452. if(valid(map) && map.GetEntireCoords(0, 0, hexX, hexY))
  453. {
  454. mapId = map.Id;
  455. dir = 0xFF;
  456. }
  457. }
  458. return;
  459. }
  460.  
  461. InviteToEncounter(group, car, encounterDescriptor, combatMode, mapId, hexX, hexY, dir);
  462. }
  463.  
  464. void ScanZone(array<Critter@>& group, int zx, int zy)
  465. {
  466. array<uint> locIds1, locIds2;
  467. bool locIds2Founded = false;
  468.  
  469. GetZoneLocationIds(zx, zy, 1, locIds1);
  470.  
  471. for(uint i = 0; i < group.length(); i++)
  472. {
  473. Critter@ cr = group[i];
  474. if(!cr.IsPlayer())
  475. continue;
  476.  
  477. int lookLen = cr.PerkBase[PE_SCOUT] != 0 ? 2 : 1;
  478.  
  479. if(lookLen == 2 && !locIds2Founded)
  480. {
  481. GetZoneLocationIds(zx, zy, 2, locIds2);
  482. locIds2Founded = true;
  483. }
  484.  
  485. // Open fog
  486. int mapw = __GlobalMapWidth;
  487. int maph = __GlobalMapHeight;
  488. for(int x = -lookLen; x <= lookLen; x++)
  489. {
  490. for(int y = -lookLen; y <= lookLen; y++)
  491. {
  492. int zx_ = zx + x;
  493. int zy_ = zy + y;
  494. if(zx_ >= 0 && zx_ < mapw && zy_ >= 0 && zy_ < maph)
  495. {
  496. int fog = (zx == zx_ && zy == zy_ ? FOG_NONE : FOG_HALF);
  497. if(cr.GetFog(zx_, zy_) < fog)
  498. cr.SetFog(zx_, zy_, fog);
  499. }
  500. }
  501. }
  502.  
  503. // Find new locations
  504. array<uint>@ locIds = lookLen == 1 ? locIds1 : locIds2;
  505. for(uint j = 0; j < locIds.length(); j++)
  506. {
  507. uint locId = locIds[j];
  508. if(!cr.IsKnownLoc(true, locId))
  509. {
  510. Location@ loc = GetLocation(locId);
  511. if(valid(loc))
  512. cr.SetKnownLoc(true, locId);
  513. }
  514. }
  515. }
  516. }
  517.  
  518. void MoveGlobalGroup(Critter& cr, Item@ car, float& curX, float& curY, float& toX, float& toY, float& speed) // export
  519. {
  520. int movementType = (valid(car) ? car.Proto.Car_MovementType : GM_WALK_GROUND);
  521.  
  522. int curXi = int(curX);
  523. int curYi = int(curY);
  524. // Save current distantion to compare in the end
  525. float lastDist = DISTANCE(curX, curY, toX, toY);
  526.  
  527. // Calcuate speed
  528. float speedPix = speed * float(__GlobalMapMoveTime) / 1000.0f;
  529. float speedAngle = atan2(toY - curY, toX - curX);
  530. float speedX = cos(speedAngle) * speedPix;
  531. float speedY = sin(speedAngle) * speedPix;
  532.  
  533. float speedMod = 1.0f;
  534. if(movementType == GM_WALK_GROUND)
  535. {
  536. // Speed modifiers
  537. // F E D C B A 9 8 7 6 5 4 3 2 1 0
  538. // 1.5 1.4 1.3 1.2 1.1 1.0 0.95 0.9 0.85 0.8 0.75 0.7 0.65 0.6 0.55 0.0
  539. switch(GetGlobalMapRelief(curXi, curYi))
  540. {
  541. case 0x0:
  542. speedMod = 1.00f;
  543. break;
  544. case 0x1:
  545. speedMod = 0.55f;
  546. break;
  547. case 0x2:
  548. speedMod = 0.60f;
  549. break;
  550. case 0x3:
  551. speedMod = 0.65f;
  552. break;
  553. case 0x4:
  554. speedMod = 0.70f;
  555. break;
  556. case 0x5:
  557. speedMod = 0.75f;
  558. break;
  559. case 0x6:
  560. speedMod = 0.80f;
  561. break;
  562. case 0x7:
  563. speedMod = 0.85f;
  564. break;
  565. case 0x8:
  566. speedMod = 0.90f;
  567. break;
  568. case 0x9:
  569. speedMod = 0.95f;
  570. break;
  571. case 0xA:
  572. speedMod = 1.00f;
  573. break;
  574. case 0xB:
  575. speedMod = 1.10f;
  576. break;
  577. case 0xC:
  578. speedMod = 1.20f;
  579. break;
  580. case 0xD:
  581. speedMod = 1.30f;
  582. break;
  583. case 0xE:
  584. speedMod = 1.40f;
  585. break;
  586. case 0xF:
  587. speedMod = 1.50f;
  588. break;
  589. default:
  590. break;
  591. }
  592. if(speedMod < 1.0f && cr.Perk[PE_EXPLORER] != 0)
  593. speedMod = speedMod / 2.0f + 0.5f;
  594. }
  595.  
  596. if(valid(car) && speedMod != 1.0f)
  597. {
  598. float pass = float(car.Proto.Car_Passability);
  599. if(pass > 100.0f && speedMod < 1.0f)
  600. speedMod += (1.0f - speedMod) * (pass - 100.0f) / 100.0f;
  601. else if(pass > 100.0f && speedMod > 1.0f)
  602. speedMod -= (speedMod - 1.0f) * (pass - 100.0f) / 100.0f;
  603. else if(pass < 100.0f && speedMod < 1.0f)
  604. speedMod -= (1.0f - speedMod) * (100.0f - pass) / 100.0f;
  605. else if(pass < 100.0f && speedMod > 1.0f)
  606. speedMod += (speedMod - 1.0f) * (100.0f - pass) / 100.0f;
  607. }
  608.  
  609. // Apply step
  610. curX += speedX * speedMod;
  611. curY += speedY * speedMod;
  612.  
  613. int oldXi = curXi;
  614. int oldYi = curYi;
  615. curXi = int(curX); // Round
  616. curYi = int(curY); // Round
  617.  
  618.  
  619. // Check new position
  620. if(oldXi != curXi || oldYi != curYi)
  621. {
  622. // Check borders
  623. int gmWidth = __GlobalMapWidth * __GlobalMapZoneLength;
  624. int gmHeight = __GlobalMapHeight * __GlobalMapZoneLength;
  625. if(curXi < 0 || curYi < 0 || curXi >= gmWidth || curYi >= gmHeight)
  626. {
  627. if(curXi < 0)
  628. curXi = 0;
  629. if(curXi >= gmWidth)
  630. curXi = gmWidth - 1;
  631. if(curYi < 0)
  632. curYi = 0;
  633. if(curYi >= gmHeight)
  634. curYi = gmHeight - 1;
  635.  
  636. // Stop group
  637. curX = float(curXi);
  638. curY = float(curYi);
  639. speed = 0.0f;
  640. return;
  641. }
  642.  
  643. // Move from old to new and find last correct position
  644. int relief = GetGlobalMapRelief(oldXi, oldYi);
  645. int steps = MAX(ABS(curXi - oldXi), ABS(curYi - oldYi));
  646. int newXi = oldXi;
  647. int newYi = oldYi;
  648. if(steps > 0)
  649. {
  650. float xx = float(oldXi);
  651. float yy = float(oldYi);
  652. float oxx = float(curXi - oldXi) / float(steps);
  653. float oyy = float(curYi - oldYi) / float(steps);
  654.  
  655. for(int i = 0; i < steps; i++)
  656. {
  657. xx += oxx;
  658. yy += oyy;
  659. int xxi = int(xx >= 0.0f ? xx + 0.5f : xx - 0.5f);
  660. int yyi = int(yy >= 0.0f ? yy + 0.5f : yy - 0.5f);
  661.  
  662. uint relief_ = GetGlobalMapRelief(xxi, yyi);
  663. if(movementType == GM_WALK_GROUND && relief != 0 && relief_ == 0)
  664. break;
  665. if(movementType == GM_WALK_WATER && relief_ != 0)
  666. break;
  667.  
  668. newXi = xxi;
  669. newYi = yyi;
  670. }
  671. }
  672.  
  673. if(newXi != curXi || newYi != curYi)
  674. {
  675. // Stop group
  676. curX = float(newXi);
  677. curY = float(newYi);
  678. speed = 0.0f;
  679. return;
  680. }
  681.  
  682. // Zone
  683. int oldZoneX = oldXi / __GlobalMapZoneLength;
  684. int oldZoneY = oldYi / __GlobalMapZoneLength;
  685. int curZoneX = curXi / __GlobalMapZoneLength;
  686. int curZoneY = curYi / __GlobalMapZoneLength;
  687.  
  688. // Change zone
  689. if(oldZoneX != curZoneX || oldZoneY != curZoneY)
  690. {
  691. array<Critter@>@ group = cr.GetGlobalGroup();
  692. ScanZone(group, curZoneX, curZoneY);
  693. }
  694.  
  695. // Check for complete travelling
  696. float curDist = DISTANCE(curX, curY, toX, toY);
  697. if(curDist <= 0.01f || curDist > lastDist)
  698. {
  699. curX = toX;
  700. curY = toY;
  701. speed = 0.0f;
  702. return;
  703. }
  704. }
  705.  
  706. // Car processing
  707. if(valid(car)) // && GetLvar(cr, LVAR_wm_idle) == 0)
  708. {
  709. int fuel = car.Charge;
  710. int deterioration = car.Deterioration;
  711.  
  712. if(fuel == 0 || deterioration >= int(car.Proto.Car_MaxDeterioration))
  713. {
  714. uint strNum = (fuel <= 0 ? STR_CAR_FUEL_EMPTY : STR_CAR_BROKEN);
  715. CarMessage(cr, car, strNum);
  716. speed = 0.0f;
  717. //SetLvar(cr, LVAR_wm_idle, 1);
  718. return;
  719. }
  720.  
  721. // Car values created for the call every 500 ms
  722. fuel -= car.Proto.Car_FuelConsumption * __GlobalMapMoveTime / 500;
  723. deterioration += car.Proto.Car_DeteriorationRate * __GlobalMapMoveTime / 500;
  724. if(fuel < 0)
  725. fuel = 0;
  726. if(deterioration > int(car.Proto.Car_MaxDeterioration))
  727. deterioration = int(car.Proto.Car_MaxDeterioration);
  728.  
  729. if(fuel != int(car.Charge) || deterioration != int(car.Deterioration))
  730. {
  731. car.Charge = fuel;
  732. car.Deterioration = deterioration;
  733. car.Update();
  734. }
  735. }
  736. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement