• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21108840797

18 Jan 2026 08:35AM UTC coverage: 60.508% (+0.02%) from 60.492%
21108840797

push

github

web-flow
ClangTidy readability-else-after-return (#857)

* trigger tidy

* Automated clang-tidy change: readability-else-after-return

* compile test

* rerun

* Automated clang-tidy change: readability-else-after-return

* trigger..

* Automated clang-tidy change: readability-else-after-return

* manually removed a few

* Automated clang-tidy change: readability-else-after-return

* removed duplicate code

* fix remaining warnings

* fixed scope

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

837 of 1874 new or added lines in 151 files covered. (44.66%)

46 existing lines in 25 files now uncovered.

44448 of 73458 relevant lines covered (60.51%)

525066.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.22
/pol-core/pol/repsys.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/12/05 MuadDib:   Added ssopt.invul_tag for Repsys::hilite_color_idx
5
 * - 2005/12/05 MuadDib:   Added ssopt.invul_tag for NPC::hilite_color_idx
6
 * - 2005/12/05 MuadDib:   Added repsys.invulnerable color for names.
7
 * - 2009/08/06 Turley:    Added escript interface to add/remove aggressor/lawfullydamaged
8
 */
9

10

11
#include "repsys.h"
12

13
#include <stddef.h>
14
#include <string>
15

16
#include "../clib/cfgelem.h"
17
#include "../clib/cfgfile.h"
18
#include "../clib/cfgsect.h"
19
#include "../clib/logfacility.h"
20
#include "../clib/rawtypes.h"
21
#include "cmbtcfg.h"
22
#include "fnsearch.h"
23
#include "globals/settings.h"
24
#include "globals/state.h"
25
#include "guilds.h"
26
#include "mobile/charactr.h"
27
#include "mobile/npc.h"
28
#include "network/pktdef.h"
29
#include "npctmpl.h"
30
#include "party.h"
31
#include "polsig.h"
32
#include "repsys_cfg.h"
33
#include "schedule.h"
34
#include "syshook.h"
35
#include "ufunc.h"
36
#include "uworld.h"
37

38
// BUGS:
39
//  it looks like you can restart someone's aggressor timer by toggling war mode and setting
40
//  opponent.
41
//
42

43
namespace Pol
44
{
45
namespace Core
46
{
47
/// Reputation System
48

49
/// [1] Reputation System Configuration
50
/// Reputation System Configuration is read from config/repsys.cfg
51
/// This file is re-read on a config reload.
52
/// [1.1] General Configuration
53
///  Settings are defined in the General section:
54
///    CriminalFlagInterval    Time, in seconds, for which you will be marked criminal
55
///    AggressorFlagTimeout    Time, in seconds, for which you will be marked an aggressor
56
///
57
///
58
/// [1.2] Color Configuration
59
///  Name colors are defined in the NameColoring section:
60
///    Murderer
61
///    Criminal
62
///    Attackable
63
///    Innocent
64
///    GuildAlly
65
///    GuildEnemy
66
///    Invulnerable
67
///  The client specifies highlight colors.
68
///
69

70
void load_repsys_cfg_namecoloring( Clib::ConfigElem& elem )
3✔
71
{
72
  settingsManager.repsys_cfg.NameColoring.Murderer = elem.remove_ushort( "Murderer" );
3✔
73
  settingsManager.repsys_cfg.NameColoring.Criminal = elem.remove_ushort( "Criminal" );
3✔
74
  settingsManager.repsys_cfg.NameColoring.Attackable = elem.remove_ushort( "Attackable" );
3✔
75
  settingsManager.repsys_cfg.NameColoring.Innocent = elem.remove_ushort( "Innocent" );
3✔
76
  settingsManager.repsys_cfg.NameColoring.GuildAlly = elem.remove_ushort( "GuildAlly" );
3✔
77
  settingsManager.repsys_cfg.NameColoring.GuildEnemy = elem.remove_ushort( "GuildEnemy" );
3✔
78
  settingsManager.repsys_cfg.NameColoring.Invulnerable = elem.remove_ushort( "Invulnerable" );
3✔
79
}
3✔
80
void load_repsys_cfg_general( Clib::ConfigElem& elem )
3✔
81
{
82
  settingsManager.repsys_cfg.General.CriminalFlagInterval =
3✔
83
      elem.remove_ushort( "CriminalFlagInterval" );
3✔
84
  settingsManager.repsys_cfg.General.AggressorFlagTimeout =
3✔
85
      elem.remove_ushort( "AggressorFlagTimeout" );
3✔
86
  settingsManager.repsys_cfg.General.PartyHelpFullCountsAsCriminal =
3✔
87
      elem.remove_bool( "PartyHelpFullCountsAsCriminal", false );
3✔
88
  settingsManager.repsys_cfg.General.PartyHarmFullCountsAsCriminal =
3✔
89
      elem.remove_bool( "PartyHarmFullCountsAsCriminal", true );
3✔
90
}
3✔
91
void load_repsys_cfg_hooks( Clib::ConfigElem& elem )
×
92
{
93
  std::string temp;
×
94
  if ( elem.remove_prop( "NameColor", &temp ) )
×
95
    settingsManager.repsys_cfg.Hooks.NameColor = FindExportedFunction( elem, nullptr, temp, 2 );
×
96
  if ( elem.remove_prop( "HighLightColor", &temp ) )
×
97
    settingsManager.repsys_cfg.Hooks.HighLightColor =
×
98
        FindExportedFunction( elem, nullptr, temp, 2 );
×
99

100
  if ( elem.remove_prop( "OnAttack", &temp ) )
×
101
    settingsManager.repsys_cfg.Hooks.OnAttack = FindExportedFunction( elem, nullptr, temp, 2 );
×
102
  if ( elem.remove_prop( "OnDamage", &temp ) )
×
103
    settingsManager.repsys_cfg.Hooks.OnDamage = FindExportedFunction( elem, nullptr, temp, 2 );
×
104
  if ( elem.remove_prop( "OnHelp", &temp ) )
×
105
    settingsManager.repsys_cfg.Hooks.OnHelp = FindExportedFunction( elem, nullptr, temp, 2 );
×
106
}
×
107

108
void unload_repsys_cfg_hooks()
3✔
109
{
110
  if ( settingsManager.repsys_cfg.Hooks.NameColor != nullptr )
3✔
111
  {
112
    delete settingsManager.repsys_cfg.Hooks.NameColor;
×
113
    settingsManager.repsys_cfg.Hooks.NameColor = nullptr;
×
114
  }
115
  if ( settingsManager.repsys_cfg.Hooks.HighLightColor != nullptr )
3✔
116
  {
117
    delete settingsManager.repsys_cfg.Hooks.HighLightColor;
×
118
    settingsManager.repsys_cfg.Hooks.HighLightColor = nullptr;
×
119
  }
120
  if ( settingsManager.repsys_cfg.Hooks.OnAttack != nullptr )
3✔
121
  {
122
    delete settingsManager.repsys_cfg.Hooks.OnAttack;
×
123
    settingsManager.repsys_cfg.Hooks.OnAttack = nullptr;
×
124
  }
125
  if ( settingsManager.repsys_cfg.Hooks.OnDamage != nullptr )
3✔
126
  {
127
    delete settingsManager.repsys_cfg.Hooks.OnDamage;
×
128
    settingsManager.repsys_cfg.Hooks.OnDamage = nullptr;
×
129
  }
130
  if ( settingsManager.repsys_cfg.Hooks.OnHelp != nullptr )
3✔
131
  {
132
    delete settingsManager.repsys_cfg.Hooks.OnHelp;
×
133
    settingsManager.repsys_cfg.Hooks.OnHelp = nullptr;
×
134
  }
135
}
3✔
136

137
void unload_repsys_cfg()
3✔
138
{
139
  unload_repsys_cfg_hooks();
3✔
140
}
3✔
141

142
void load_repsys_cfg( bool reload )
3✔
143
{
144
  Clib::ConfigFile cf( "config/repsys.cfg" );
3✔
145

146
  Clib::ConfigSection namecoloring( cf, "NameColoring" );
3✔
147
  Clib::ConfigSection general( cf, "General" );
3✔
148
  Clib::ConfigSection hooks( cf, "HookList", Clib::CST_NORMAL );
3✔
149

150
  Clib::ConfigElem elem;
3✔
151

152
  while ( cf.read( elem ) )
9✔
153
  {
154
    if ( namecoloring.matches( elem ) )
6✔
155
    {
156
      load_repsys_cfg_namecoloring( elem );
3✔
157
    }
158
    else if ( general.matches( elem ) )
3✔
159
    {
160
      load_repsys_cfg_general( elem );
3✔
161
    }
162
    else if ( hooks.matches( elem ) && !reload )
×
163
    {
164
      load_repsys_cfg_hooks( elem );
×
165
    }
166
  }
167
}
3✔
168

169
///
170
/// [2] Timeouts
171
/// When Any of Amy's Rep-system timers time out
172
///
173
/// If Amy's Criminal Timer has expired,
174
///   Clear Amy's Criminal Timer
175
///
176
/// If Amy was Aggressor to Bob, but has timed out
177
///   De-escalate[->7] Amy and Bob
178
///   Update Bob to nearby clients
179
///
180
/// If Amy had Lawfully Damaged Bob, but has timed out
181
///   De-escalate[->7] Amy and Bob
182
///   Update Bob to nearby clients
183
///
184
/// If any of Amy's statuses changed,
185
///   Update Amy to nearby clients
186

187
void RepSystem::repsys_task( Mobile::Character* amy )
1✔
188
{
189
  THREAD_CHECKPOINT( tasks, 1000 );
1✔
190
  polclock_t now = polclock();
1✔
191
  bool refreshall = false;
1✔
192

193
  // the 'defensive hostiles' are those that are attacking Amy while she's not innocent.
194
  // If she's innocent at the end of this, they will break off the attack.
195
  THREAD_CHECKPOINT( tasks, 1001 );
1✔
196
  Mobile::Character::CharacterSet defensive_hostiles;
1✔
197
  for ( Mobile::Character::CharacterSet::iterator h_itr = amy->opponent_of.begin();
1✔
198
        h_itr != amy->opponent_of.end(); ++h_itr )
1✔
199
  {
200
    Mobile::Character* hostile_bob = *h_itr;
×
201
    THREAD_CHECKPOINT( tasks, 1002 );
×
202

203
    if ( !amy->is_innocent_to( hostile_bob ) )
×
204
    {
205
      THREAD_CHECKPOINT( tasks, 1003 );
×
206
      defensive_hostiles.insert( hostile_bob );
×
207
    }
208
    THREAD_CHECKPOINT( tasks, 1004 );
×
209
  }
210

211

212
  THREAD_CHECKPOINT( tasks, 1005 );
1✔
213
  if ( amy->criminal_until_ && timer_expired( amy->criminal_until_, now ) )
1✔
214
  {
215
    amy->criminal_until_ = 0;
×
216
    refreshall = true;
×
217
  }
218

219
  THREAD_CHECKPOINT( tasks, 1006 );
1✔
220
  polclock_t earliest_timeout;
221

222
  if ( amy->criminal_until_ )
1✔
223
    earliest_timeout = amy->criminal_until_;
×
224
  else
225
    earliest_timeout = now + 5 * 60 * POLCLOCKS_PER_SEC;  // 5 minutes, later code will trim
1✔
226

227
  THREAD_CHECKPOINT( tasks, 1007 );
1✔
228

229
  Mobile::Character::MobileCont::iterator itr;
1✔
230
  itr = amy->aggressor_to_.begin();
1✔
231
  while ( itr != amy->aggressor_to_.end() )
1✔
232
  {
233
    THREAD_CHECKPOINT( tasks, 1008 );
×
234
    Mobile::Character::MobileCont::iterator save_itr = itr;
×
235
    ++itr;
×
236
    polclock_t when = ( *save_itr ).second;
×
237
    THREAD_CHECKPOINT( tasks, 1009 );
×
238
    if ( timer_expired( when, now ) )
×
239
    {
240
      THREAD_CHECKPOINT( tasks, 1010 );
×
241
      CharacterRef other = ( *save_itr ).first;
×
242
      // not sure if this is right.  what if also lawfully_damaged ?
243
      THREAD_CHECKPOINT( tasks, 1011 );
×
244
      de_escalate( amy, other.get() );
×
245
      THREAD_CHECKPOINT( tasks, 1012 );
×
246
      amy->aggressor_to_.erase( save_itr );
×
247
      THREAD_CHECKPOINT( tasks, 1013 );
×
248
      if ( !other->orphan() )
×
249
      {
250
        // Changed to update!
251
        if ( amy->client )
×
252
          send_move( amy->client, amy );
×
253
        send_create_mobile_to_nearby_cansee( other.get() );
×
254
      }
255
      else
256
        POLLOGLN( "NOTE: repsys crash avoidance..." );
×
257
      THREAD_CHECKPOINT( tasks, 1014 );
×
258
      refreshall = true;
×
259
    }
×
260
    else
261
    {
262
      earliest_timeout = earliest_timer( when, earliest_timeout );
×
263
    }
264
    THREAD_CHECKPOINT( tasks, 1015 );
×
265
  }
266

267
  THREAD_CHECKPOINT( tasks, 1016 );
1✔
268
  itr = amy->lawfully_damaged_.begin();
1✔
269
  while ( itr != amy->lawfully_damaged_.end() )
1✔
270
  {
271
    THREAD_CHECKPOINT( tasks, 1017 );
×
272
    Mobile::Character::MobileCont::iterator save_itr = itr;
×
273
    ++itr;
×
274
    polclock_t when = ( *save_itr ).second;
×
275
    THREAD_CHECKPOINT( tasks, 1018 );
×
276
    if ( timer_expired( when, now ) )
×
277
    {
278
      THREAD_CHECKPOINT( tasks, 1019 );
×
279
      CharacterRef other = ( *save_itr ).first;
×
280
      // not sure if this is right.  what if also aggressor_to ?
281
      THREAD_CHECKPOINT( tasks, 1020 );
×
282
      de_escalate( amy, other.get() );
×
283
      THREAD_CHECKPOINT( tasks, 1021 );
×
284
      amy->lawfully_damaged_.erase( save_itr );
×
285
      THREAD_CHECKPOINT( tasks, 1022 );
×
286
      if ( !other->orphan() )
×
287
      {
288
        // Changed to update!
289
        if ( amy->client )
×
290
          send_move( amy->client, amy );
×
291
        send_create_mobile_to_nearby_cansee( other.get() );
×
292
      }
293
      else
294
        POLLOGLN( "NOTE: repsys crash avoidance..." );
×
295
      THREAD_CHECKPOINT( tasks, 1023 );
×
296
      refreshall = true;
×
297
    }
×
298
    else
299
    {
300
      earliest_timeout = earliest_timer( when, earliest_timeout );
×
301
    }
302
    THREAD_CHECKPOINT( tasks, 1024 );
×
303
  }
304

305
  THREAD_CHECKPOINT( tasks, 1025 );
1✔
306
  // For those that were hostile to Amy due to her non-Innocence, if she's Innocent now,
307
  // break off the attack.
308
  for ( Mobile::Character::CharacterSet::iterator h_itr = defensive_hostiles.begin();
1✔
309
        h_itr != defensive_hostiles.end(); ++h_itr )
1✔
310
  {
311
    Mobile::Character* bob = *h_itr;
×
312
    THREAD_CHECKPOINT( tasks, 1026 );
×
313

314
    if ( amy->is_innocent_to( bob ) )
×
315
    {
316
      THREAD_CHECKPOINT( tasks, 1027 );
×
317
      de_escalate( amy, bob );
×
318
      THREAD_CHECKPOINT( tasks, 1028 );
×
319

320
      refreshall = true;
×
321
    }
322
  }
323

324
  THREAD_CHECKPOINT( tasks, 1029 );
1✔
325

326
  if ( amy->criminal_until_ || !amy->aggressor_to_.empty() || !amy->lawfully_damaged_.empty() )
1✔
327
  {
328
    THREAD_CHECKPOINT( tasks, 1030 );
×
329
    schedule_repsys_task( amy, earliest_timeout + 1 );
×
330
  }
331

332
  THREAD_CHECKPOINT( tasks, 1031 );
1✔
333
  if ( refreshall )
1✔
334
  {
335
    THREAD_CHECKPOINT( tasks, 1032 );
×
336
    if ( !amy->orphan() )
×
337
    {
338
      // Changed to update!
339
      if ( amy->client )
×
340
        send_move( amy->client, amy );
×
341
      send_create_mobile_to_nearby_cansee( amy );
×
342
    }
343
  }
344
  THREAD_CHECKPOINT( tasks, 1099 );
1✔
345
}
1✔
346

347

348
void RepSystem::schedule_repsys_task( Mobile::Character* chr, polclock_t runat )
3✔
349
{
350
  if ( chr->repsys_task_ != nullptr )
3✔
351
  {
352
    if ( chr->repsys_task_->next_run_clock() > runat )
×
353
      chr->repsys_task_->cancel();
×
354
  }
355

356
  if ( chr->repsys_task_ == nullptr )
3✔
357
  {
358
    new OneShotTaskInst<Mobile::Character*>( &chr->repsys_task_, runat, RepSystem::repsys_task,
3✔
359
                                             chr );
3✔
360
  }
361
}
3✔
362
bool private_say_above_ex( Mobile::Character* chr, const UObject* obj, const char* text,
363
                           unsigned short color );
364
// bool RepSystem::can_attack( Character* attacker, Character* defender )
365
// {
366
//   return (defender->is_aggressor_to( attacker ) ||
367
//     attacker->has_lawfully_damaged(defender) ||
368
//     defender->is_criminal());
369
// }
370
//
371

372
// a scenario:
373
// A (innocent) attacks B (innocent):
374
//   (3), so A criminal, aggressor to B
375
// A (crim,agg) attacks B (innocent):
376
//   (1), so A's aggressor timer restarts (not criminal timer)
377
// B (innocent) attacks A (crim,agg):
378
//   (2b), so lawfully damaged timer restarts
379
// B (innocent) attacks A (crim,agg):
380
//   (2a), so lawfully damaged timer restarts
381
// A (crim, agg) attacks B (innocent):
382
//   umm, what should happen?
383

384

385
///
386
/// [3] Player attacks another Player
387
/// When Amy attacks Bob
388
///   These rules are applied:
389
///   - When Amy applies damage to Bob (on_pc_damaged_pc calls this)
390
///   - repsys_on_attack (Amy attacks PC, or tamed creature)
391
///     - apply_raw_damage_hundredths
392
///     - amy sets opponent
393
///     - melee attack
394
///     - amy's NPC does any of these things
395
///   - When Amy tries to apply any damage to Bob
396
///   - When Amy selects Bob as her Opponent
397
///   - When Amy swings at Bob
398
///   - When Amy selects Bob with a Harmful target cursor
399
///
400
///   if Bob is Innocent to Amy,
401
///     Set Amy's Criminal flag for CriminalFlagInterval seconds
402
///
403
///   if Bob is Aggressor to Amy,
404
///     Set Bob as Aggressor to Amy for AggressorFlagTimeout seconds
405
///   else,
406
///     Tell Bob "Amy is Attacking you!" if this is news
407
///     Set Amy as Aggressor to Bob for AggressorFlagTimeout seconds
408
///
409

410
void RepSystem::on_pc_attacks_pc( Mobile::Character* amy_attacker, Mobile::Character* bob_defender )
2✔
411
{
412
  if ( amy_attacker == bob_defender )
2✔
413
    return;
1✔
414

415
  bool refresh = false;
1✔
416

417
  polclock_t now = polclock();
1✔
418
  polclock_t crim_timeout_at =
1✔
419
      now + settingsManager.repsys_cfg.General.CriminalFlagInterval * POLCLOCKS_PER_SEC;
1✔
420
  polclock_t aggr_timeout_at =
1✔
421
      now + settingsManager.repsys_cfg.General.AggressorFlagTimeout * POLCLOCKS_PER_SEC;
1✔
422

423
  if ( bob_defender->is_innocent_to( amy_attacker ) )
1✔
424
  {
425
    if ( !amy_attacker->is_criminal() )
1✔
426
      refresh = true;
1✔
427
    amy_attacker->restart_criminal_timer( crim_timeout_at );
1✔
428
  }
429

430
  if ( bob_defender->is_aggressor_to( amy_attacker ) )
1✔
431
  {
432
    bob_defender->restart_aggressor_timer( amy_attacker, aggr_timeout_at );
×
433
  }
434
  else  // he's not the aggressor, so I guess I am.
435
  {
436
    if ( !amy_attacker->is_aggressor_to( bob_defender ) )
1✔
437
    {
438
      if ( settingsManager.combat_config.send_attack_msg )
1✔
439
      {
440
        std::string msg = "*" + amy_attacker->name() + " is attacking you!*";
1✔
441
        private_say_above_ex( bob_defender, bob_defender, msg.c_str(),
1✔
442
                              settingsManager.repsys_cfg.NameColoring.Murderer );
1✔
443
      }
1✔
444
      refresh = true;
1✔
445
    }
446
    amy_attacker->restart_aggressor_timer( bob_defender, aggr_timeout_at );
1✔
447
  }
448

449
  if ( refresh )
1✔
450
  {
451
    // Changed to update!
452
    if ( amy_attacker->client )
1✔
453
      send_move( amy_attacker->client, amy_attacker );
×
454
    send_create_mobile_to_nearby_cansee( amy_attacker );
1✔
455
  }
456
  polclock_t timeout_at = earliest_timer( crim_timeout_at, aggr_timeout_at );
1✔
457

458
  schedule_repsys_task( amy_attacker, timeout_at + 1 );
1✔
459
  schedule_repsys_task( bob_defender, timeout_at + 1 );
1✔
460
}
461

462
///
463
/// [4] Player Damages Player
464
/// When Amy damages Bob
465
///   These rules applied:
466
///   - When Amy actually applies damage to Bob
467
///   - When Amy poisons Bob (only with Bob.SetPoisoned(1))
468
///     (note damage due to poisoning will not fire this rule,
469
///     only the initial application)
470
///   - When Amy paralyzes Bob (only with Bob.SetParalyzed(1))
471
///
472
///   Apply all rules for "Player Attacks Another Player"[->3]
473
///
474
///   If Bob is Innocent to Amy,
475
///     Add Amy to Bob's "ToBeReportable" list
476
///   else
477
///     Set Amy as having LawfullyDamaged Bob for AggressorFlagTimeout seconds
478
///
479
///
480
///
481
void RepSystem::on_pc_damages_pc( Mobile::Character* amy, Mobile::Character* bob )
1✔
482
{
483
  if ( amy == bob )
1✔
484
    return;
×
485
  polclock_t aggr_timeout_at =
486
      polclock() + settingsManager.repsys_cfg.General.AggressorFlagTimeout * POLCLOCKS_PER_SEC;
1✔
487

488
  on_pc_attacks_pc( amy, bob );
1✔
489

490
  if ( bob->is_innocent_to( amy ) )
1✔
491
  {
492
    bob->add_to_be_reportable( amy->serial );
1✔
493
  }
494
  else
495
  {
496
    amy->restart_lawfully_damaged_timer( bob, aggr_timeout_at );
×
497
    schedule_repsys_task( amy, aggr_timeout_at + 1 );
×
498
  }
499
}
500

501

502
///
503
/// [5] Player Helps Another Player
504
/// When Amy Helps Bob
505
///   These rules applied:
506
///   - When Amy selects Bob with a Helpful target cursor
507
///   - When Amy Heals Bob
508
///   - When Amy clear's Bob's Poisoned flag
509
///   - When Amy clear's Bob's Paralyzed flag
510
///
511
/// If PartyHelpFullCountsAsCriminal false and same party dont set
512
///  If Bob is a Criminal, Set Amy Criminal
513
///
514

515
void RepSystem::on_pc_helps_pc( Mobile::Character* amy, Mobile::Character* bob )
×
516
{
517
  if ( ( amy != bob ) && bob->is_criminal() )
×
518
  {
519
    if ( !settingsManager.repsys_cfg.General.PartyHelpFullCountsAsCriminal )
×
520
    {
521
      Party* party = amy->party();
×
522
      if ( ( party != nullptr ) && ( party->is_member( bob->serial ) ) )
×
523
        return;
×
524
    }
525
    amy->make_criminal();
×
526
  }
527
}
528

529
/// [7] De-Escalation
530
/// To De-escalate Amy and Bob:
531
///   if Amy's opponent is Bob, Amy clears her opponent
532
///   If Bob's opponent is Amy, Bob clears his opponent
533
///
534

535
void RepSystem::de_escalate( Mobile::Character* amy, Mobile::Character* bob )
×
536
{
537
  if ( amy->opponent_ == bob )
×
538
  {
539
    amy->set_opponent( nullptr, true );
×
540
  }
541

542
  if ( bob->opponent_ == amy )
×
543
  {
544
    bob->set_opponent( nullptr, true );
×
545
  }
546
}
×
547

548
///
549
/// [8] Highlighting and Name Coloring
550
///   if Amy looks at Bob, coloring is as follows:
551
///     if Bob is invul and invul tag set 2, color Bob INVUL (yellow)
552
///     if Bob is a Murderer                 color Bob MURDERER ()
553
///     if Bob is a Criminal,                color Bob CRIMINAL (Red)
554
///     If Bob is a guild ally of Amy's,     color Bob FRIEND (Green)
555
///     if Bob is an Aggressor to Amy,       color Bob ATTACKABLE (Grey)
556
///     if Amy has lawfully damaged Bob,     color Bob ATTACKABLE (Grey)
557
///     if Bob is a guild enemy of Amy's,    color Bob ENEMY (Orange)
558
///     otherwise                            color Bob INNOCENT (Blue)
559
///
560

561
unsigned char RepSystem::hilite_color_idx( const Mobile::Character* amy,
104✔
562
                                           const Mobile::Character* bob )
563
{
564
  if ( settingsManager.repsys_cfg.Hooks.HighLightColor )
104✔
565
  {
566
    Mobile::Character* t_amy = const_cast<Mobile::Character*>( amy );
×
567
    Mobile::Character* t_bob = const_cast<Mobile::Character*>( bob );
×
568
    int hook_highlight = settingsManager.repsys_cfg.Hooks.HighLightColor->call_long(
×
569
        t_bob->make_ref(), t_amy->make_ref() );
×
570
    if ( hook_highlight != -1 )
×
571
      return (unsigned char)hook_highlight;
×
572
  }
573

574
  if ( ( settingsManager.ssopt.invul_tag == 2 ) && bob->invul() )
104✔
575
    return CHAR_HILITE_INVUL;
×
576
  if ( bob->is_murderer() )
104✔
577
    return CHAR_HILITE_MURDERER;
×
578
  if ( bob->is_criminal() )
104✔
579
    return CHAR_HILITE_CRIMINAL;
×
580
  if ( bob->is_guild_ally( amy ) )
104✔
581
    return CHAR_HILITE_FRIEND;
×
582
  if ( bob->is_aggressor_to( amy ) || amy->has_lawfully_damaged( bob ) )
104✔
583
    return CHAR_HILITE_ATTACKABLE;
×
584
  if ( bob->is_guild_enemy( amy ) )
104✔
585
    return CHAR_HILITE_ENEMY;
×
586

587
  return CHAR_HILITE_INNOCENT;
104✔
588
}
589

590
/*
591
 * AMY = Mobile doing the seeing
592
 * BOB = Mobile being seen.
593
 *
594
 */
595
unsigned short RepSystem::name_color( const Mobile::Character* amy, const Mobile::Character* bob )
30✔
596
{
597
  if ( settingsManager.repsys_cfg.Hooks.NameColor )
30✔
598
  {
599
    Mobile::Character* t_amy = const_cast<Mobile::Character*>( amy );
×
600
    Mobile::Character* t_bob = const_cast<Mobile::Character*>( bob );
×
601
    int hook_color = settingsManager.repsys_cfg.Hooks.NameColor->call_long( t_bob->make_ref(),
×
602
                                                                            t_amy->make_ref() );
×
603
    if ( hook_color != -1 )
×
604
      return (unsigned short)hook_color;
×
605
  }
606

607
  if ( settingsManager.ssopt.invul_tag == 2 )
30✔
608
  {
609
    if ( bob->invul() )
×
610
      return settingsManager.repsys_cfg.NameColoring.Invulnerable;
×
611
  }
612
  if ( bob->is_murderer() )
30✔
613
    return settingsManager.repsys_cfg.NameColoring.Murderer;
×
614
  if ( bob->is_criminal() )
30✔
615
    return settingsManager.repsys_cfg.NameColoring.Criminal;
×
616
  if ( bob->is_guild_ally( amy ) )
30✔
617
    return settingsManager.repsys_cfg.NameColoring.GuildAlly;
×
618
  if ( bob->is_aggressor_to( amy ) || amy->has_lawfully_damaged( bob ) )
30✔
619
    return settingsManager.repsys_cfg.NameColoring.Attackable;
×
620
  if ( bob->is_guild_enemy( amy ) )
30✔
621
    return settingsManager.repsys_cfg.NameColoring.GuildEnemy;
×
622
  return settingsManager.repsys_cfg.NameColoring.Innocent;
30✔
623
}
624
}  // namespace Core
625
namespace Mobile
626
{
627
///
628
/// [9] Innocent Status
629
/// Bob is Innocent to Amy if:
630
/// ===============================
631
/// Bob is Innocent to Amy only if NONE of the following are true:
632
///   Bob is a murderer;
633
///   Bob is a criminal
634
///   Bob is an Aggressor to Amy
635
///   Bob is a Guild Ally of Amy
636
///   Bob is a Guild Enemy of Amy
637
///   Amy has Lawfully Damaged Bob
638
///   If PartyHarmFullCountsAsCriminal true and Bob is in same Party as Amy
639
///
640
bool Character::is_innocent_to( const Character* amy ) const
2✔
641
{
642
  // this == bob
643
  const Character& bob = *this;
2✔
644

645
  if ( bob.is_murderer() )
2✔
646
    return false;
×
647

648
  if ( bob.is_criminal() )
2✔
649
    return false;
×
650

651
  if ( bob.is_aggressor_to( amy ) )
2✔
652
    return false;
×
653

654
  if ( bob.is_guild_ally( amy ) )
2✔
655
    return false;
×
656

657
  if ( bob.is_guild_enemy( amy ) )
2✔
658
    return false;
×
659

660
  if ( amy->has_lawfully_damaged( &bob ) )
2✔
661
    return false;
×
662

663
  if ( !Core::settingsManager.repsys_cfg.General.PartyHarmFullCountsAsCriminal )
2✔
664
  {
665
    Core::Party* party = amy->party();
×
666
    if ( ( party != nullptr ) && ( party->is_member( bob.serial ) ) )
×
667
      return false;
×
668
  }
669

670
  return true;
2✔
671
}
672

673
bool Character::is_aggressor_to( const Character* chr ) const
138✔
674
{
675
  Character* in_chr = const_cast<Character*>( chr );
138✔
676
  return ( aggressor_to_.find( Core::CharacterRef( in_chr ) ) != aggressor_to_.end() );
138✔
677
}
678

679
///
680
/// [10] Guild Rules
681
/// The following Guild Rules are only temporary pending a more complete system
682
///
683
/// [10.1] Guild Allies
684
/// Bob and Amy are Guild Allies if:
685
///   Bob is in a guild, AND
686
///   Amy is in a guild, AND
687
///   Bob's Guild is allied with Amy's guild
688
///
689
bool Character::is_guild_ally( const Character* chr ) const
136✔
690
{
691
  auto thisguild = guild();
136✔
692
  auto otherguild = chr->guild();
136✔
693
  return ( thisguild != nullptr && otherguild != nullptr &&
136✔
694
           Core::Guild::AreAllies( thisguild, otherguild ) );
136✔
695
}
696

697
///
698
/// [10.2] Guild Enemies
699
/// Bob and Amy are Guild Enemies if:
700
///   Bob is in a guild, AND
701
///   Amy is in a guild, AND
702
///   Bob's Guild is an Enemy Guild of Amy's Guild
703
///
704
///
705
bool Character::is_guild_enemy( const Character* chr ) const
136✔
706
{
707
  auto thisguild = guild();
136✔
708
  auto otherguild = chr->guild();
136✔
709
  return ( thisguild != nullptr && otherguild != nullptr &&
136✔
710
           Core::Guild::AreEnemies( thisguild, otherguild ) );
136✔
711
}
712

713
//
714
// To Mark Bob an Aggressor to Amy:
715
//   Bob is reported as an Aggressor to Amy for 2 minutes
716
//
717
//
718
void Character::restart_aggressor_timer( Character* amy, Core::polclock_t until )
1✔
719
{
720
  MobileCont::iterator itr = aggressor_to_.find( Core::CharacterRef( amy ) );
1✔
721
  if ( itr == aggressor_to_.end() )
1✔
722
  {
723
    aggressor_to_[Core::CharacterRef( amy )] = until;
1✔
724
  }
725
  else
726
  {
727
    if ( until > ( *itr ).second )
×
728
      ( *itr ).second = until;
×
729
  }
730
}
1✔
731

732
bool Character::has_lawfully_damaged( const Character* chr ) const
136✔
733
{
734
  Character* in_chr = const_cast<Character*>( chr );
136✔
735
  return ( lawfully_damaged_.find( Core::CharacterRef( in_chr ) ) != lawfully_damaged_.end() );
136✔
736
}
737

738
void Character::restart_lawfully_damaged_timer( Mobile::Character* amy, Core::polclock_t when )
×
739
{
740
  MobileCont::iterator itr = lawfully_damaged_.find( Core::CharacterRef( amy ) );
×
741
  if ( itr == lawfully_damaged_.end() )
×
742
  {
743
    lawfully_damaged_[Core::CharacterRef( amy )] = when;
×
744
  }
745
  else
746
  {
747
    if ( when > ( *itr ).second )
×
748
      ( *itr ).second = when;
×
749
  }
750
}
×
751

752
///
753
/// A Mobile is Criminal if:
754
///   he has an active Criminal Timer, which has not timed out.
755
///     OR
756
///   he is a murderer.
757
///
758
bool Character::is_criminal() const
137✔
759
{
760
  return is_temporally_criminal() || is_murderer();
137✔
761
}
762
bool Character::is_temporally_criminal() const
137✔
763
{
764
  return ( Core::polclock() <= criminal_until_ );
137✔
765
}
766

767
void Character::restart_criminal_timer( Core::polclock_t until )
1✔
768
{
769
  if ( until > criminal_until_ )
1✔
770
  {
771
    if ( criminal_until_ < Core::polclock() )
1✔
772
    {
773
      // TODO Pos see realm.cpp
774
      Core::WorldIterator<Core::NPCFilter>::InRange(
1✔
775
          this, 32, [&]( Character* chr ) { NpcPropagateCriminal( chr, this ); } );
1✔
776
    }
777
    criminal_until_ = until;
1✔
778
  }
779
}
1✔
780

781
void Character::clear_criminal_timer()
×
782
{
783
  criminal_until_ = 0;
×
784
}
×
785

786
bool Character::is_murderer() const
299✔
787
{
788
  return mob_flags_.get( MOB_FLAGS::MURDERER );
299✔
789
}
790

791

792
//
793
// Everything below this point is DOUBLE-DISPATCH for
794
//  PC vs NPC, NPC vs PC, NPC vs NPC
795
//  as well as PC -> NPC reactions.
796
//
797

798
/* the reputation system only comes into play if:
799
      a player attacks a player
800
      a player attacks a player's creature
801
      a player's creature attacks a player
802
      a player's creature attacks a player's creature
803
      */
804

805

806
///
807
/// [13] Mobile (MA) Attacks Mobile (MA)
808
///
809
///   Rules are applied based on whether MA is a PC or an NPC.
810
///
811
/// [13.1] Player (Amy) Attacks Mobile (Mob)
812
///   If Mob is a PC (Bob),
813
///     Apply 'Player Attacks Player' rules[->3] for Amy vs Bob.
814
///   Else if Mob is an NPC with a Master (Bob),
815
///     Apply 'Player Attacks Player' rules for Amy vs Bob
816
///   Else if Mob is a Good-aligned NPC,
817
///     Set Amy's Criminal Flag
818
///
819
void Character::repsys_on_attack( Character* defender )
1✔
820
{
821
  if ( Core::settingsManager.repsys_cfg.Hooks.OnAttack )
1✔
822
  {
823
    if ( Core::settingsManager.repsys_cfg.Hooks.OnAttack->call( this->make_ref(),
×
824
                                                                defender->make_ref() ) )
×
825
      return;
×
826
  }
827

828
  // consider double-dispatch here.
829
  if ( defender->isa( Core::UOBJ_CLASS::CLASS_CHARACTER ) )
1✔
830
  {
831
    Core::RepSystem::on_pc_attacks_pc( this, defender );
1✔
832
  }
833
  else
834
  {
835
    NPC* npc = static_cast<NPC*>( defender );
×
836
    if ( npc->master() )
×
837
    {
838
      Core::RepSystem::on_pc_attacks_pc( this, npc->master() );
×
839
    }
840
    else if ( ( npc->alignment() == Core::NpcTemplate::GOOD ) && ( !npc->is_criminal() ) )
×
841
    {
842
      make_criminal();
×
843
    }
844
  }
845
}
846

847
///
848
/// [13.2] NPC (MA) Attacks Mobile (MB)
849
///   If MA has a Master (Amy),
850
///     Apply 'Player Attacks Mobile' rules[->13.1] for Amy vs MB
851
///   Else
852
///     Exit with no (RepSystem) effect.
853
///
854
void NPC::repsys_on_attack( Character* defender )
12✔
855
{
856
  if ( Core::settingsManager.repsys_cfg.Hooks.OnAttack )
12✔
857
  {
858
    if ( Core::settingsManager.repsys_cfg.Hooks.OnAttack->call( this->make_ref(),
×
859
                                                                defender->make_ref() ) )
×
860
      return;
×
861
  }
862

863
  if ( master() )
12✔
864
  {
865
    master_->Character::repsys_on_attack( defender );
×
866
  }
867
}
868

869
///
870
/// [14] Mobile (MA) Damages Mobile (MB)
871
///
872
///   Rules are applied based on whether MA is a PC or an NPC.
873
///
874
/// [14.1] Player (Amy) Damages Mobile (Mob)
875
///   If Mob is a PC (Bob),
876
///     Apply 'Player Damages Player' rules[->4] for Amy vs Bob.
877
///   Else if Mob is an NPC with a Master (Bob),
878
///     Apply 'Player Damages Player' rules for Amy vs Bob
879
///   Else if Mob is a Good-aligned NPC,
880
///     Set Amy's Criminal Flag
881
///
882
void Character::repsys_on_damage( Character* defender )
1✔
883
{
884
  if ( Core::settingsManager.repsys_cfg.Hooks.OnDamage )
1✔
885
  {
886
    if ( Core::settingsManager.repsys_cfg.Hooks.OnDamage->call( this->make_ref(),
×
887
                                                                defender->make_ref() ) )
×
888
      return;
×
889
  }
890

891
  if ( defender->isa( Core::UOBJ_CLASS::CLASS_CHARACTER ) )
1✔
892
  {
893
    Core::RepSystem::on_pc_damages_pc( this, defender );
1✔
894
  }
895
  else
896
  {
897
    NPC* npc = static_cast<NPC*>( defender );
×
898
    if ( npc->master() )
×
899
    {
900
      Core::RepSystem::on_pc_damages_pc( this, npc->master() );
×
901
    }
902
    else if ( ( npc->alignment() == Core::NpcTemplate::GOOD ) && ( !npc->is_criminal() ) )
×
903
    {
904
      make_criminal();
×
905
    }
906
  }
907
}
908

909
///
910
/// [14.2] NPC (MA) Damages Mobile (MB)
911
///   If MA has a Master (Amy),
912
///     Apply 'Player Damages Mobile' rules[->14.1] for Amy vs MB
913
///   Else
914
///     Exit with no (RepSystem) effect.
915
///
916
void NPC::repsys_on_damage( Character* defender )
8✔
917
{
918
  if ( Core::settingsManager.repsys_cfg.Hooks.OnDamage )
8✔
919
  {
920
    if ( Core::settingsManager.repsys_cfg.Hooks.OnDamage->call( this->make_ref(),
×
921
                                                                defender->make_ref() ) )
×
922
      return;
×
923
  }
924

925
  if ( master() )
8✔
926
    master_->Character::repsys_on_damage( defender );
×
927
}
928

929
///
930
/// [15] Mobile (MA) Helps Mobile (MB)
931
///
932
///   Rules are applied based on whether MA is a PC or an NPC.
933
///
934
///   [15.1] Player (Amy) Helps Mobile (Mob)
935
///   If Mob is a PC (Bob),
936
///     Apply 'Player Helps Player' rules[->5] for Amy helps Bob.
937
///   Else if Mob is an NPC with a Master (Bob),
938
///     Apply 'Player Helps Player' rules for Amy helps Bob
939
///   Else if Mob is an Evil-aligned NPC,
940
///     Set Amy's Criminal Flag
941

942
void Character::repsys_on_help( Character* helped )
×
943
{
944
  if ( Core::settingsManager.repsys_cfg.Hooks.OnHelp )
×
945
  {
946
    if ( Core::settingsManager.repsys_cfg.Hooks.OnHelp->call( this->make_ref(),
×
947
                                                              helped->make_ref() ) )
×
948
      return;
×
949
  }
950

951
  // repsys_on_pc_helps( helped );
952
  if ( helped->isa( Core::UOBJ_CLASS::CLASS_CHARACTER ) )
×
953
  {
954
    Core::RepSystem::on_pc_helps_pc( this, helped );
×
955
  }
956
  else
957
  {
958
    NPC* npc = static_cast<NPC*>( helped );
×
959
    if ( npc->master() )
×
960
    {
961
      Core::RepSystem::on_pc_helps_pc( this, npc->master() );
×
962
    }
963
    else if ( npc->alignment() == Core::NpcTemplate::EVIL )
×
964
    {
965
      make_criminal();
×
966
    }
967
  }
968
}
969

970
///
971
///   [15.2] NPC (MA) Helps Mobile (MB)
972
///     If MA has a Master (Amy),
973
///       Apply 'Player Helps Mobile' rules[->15.1] for Amy helps MB
974
///     Else
975
///       Exit with no (RepSystem) effect.
976
///
977
void NPC::repsys_on_help( Character* helped )
×
978
{
979
  if ( Core::settingsManager.repsys_cfg.Hooks.OnHelp )
×
980
  {
981
    if ( Core::settingsManager.repsys_cfg.Hooks.OnHelp->call( this->make_ref(),
×
982
                                                              helped->make_ref() ) )
×
983
      return;
×
984
  }
985

986
  // repsys_on_npc_helps( helped );
987
  if ( master() )
×
988
    master_->Character::repsys_on_help( helped );
×
989
}
990

991
unsigned char Character::hilite_color_idx( const Character* seen_by ) const
104✔
992
{
993
  return Core::RepSystem::hilite_color_idx( seen_by, this );
104✔
994
}
995
unsigned short Character::name_color( const Character* seen_by ) const
12✔
996
{
997
  return Core::RepSystem::name_color( seen_by, this );
12✔
998
}
999

1000
///
1001
/// [16] NPC Highlighting
1002
///   If the NPC has a master,
1003
///     Highlight color is the same as the Master's.
1004
///   Else the NPC is invul
1005
///     Hilite them invul is ssopt.cfg option says to.
1006
///   Else
1007
///     Highlight Good NPCs   INNOCENT (Blue)
1008
///     Highlight Neutral NPCs  ATTACKABLE (Grey)
1009
///     Highlight Evil NPCs   MURDERER (Red)
1010
///
1011
unsigned char NPC::hilite_color_idx( const Character* seen_by ) const
46✔
1012
{
1013
  if ( Core::settingsManager.repsys_cfg.Hooks.HighLightColor )
46✔
1014
  {
1015
    NPC* t_amy = const_cast<NPC*>( this );
×
1016
    Character* t_bob = const_cast<Character*>( seen_by );
×
1017
    int hook_highlight = Core::settingsManager.repsys_cfg.Hooks.HighLightColor->call_long(
×
1018
        t_amy->make_ref(), t_bob->make_ref() );
×
1019
    if ( hook_highlight != -1 )
×
1020
      return (unsigned char)( hook_highlight );
×
1021
  }
1022

1023
  if ( Core::settingsManager.ssopt.invul_tag == 2 )
46✔
1024
  {
1025
    if ( invul() )
×
1026
      return CHAR_HILITE_INVUL;
×
1027
  }
1028
  if ( master() )
46✔
1029
  {
1030
    return Core::RepSystem::hilite_color_idx( seen_by, master() );
×
1031
  }
1032

1033
  switch ( template_->alignment )
46✔
1034
  {
1035
  case Core::NpcTemplate::NEUTRAL:
46✔
1036
    return CHAR_HILITE_ATTACKABLE;
46✔
NEW
1037
  case Core::NpcTemplate::GOOD:
×
NEW
1038
    if ( is_murderer() )
×
NEW
1039
      return CHAR_HILITE_MURDERER;
×
NEW
1040
    else if ( is_criminal() )
×
NEW
1041
      return CHAR_HILITE_ATTACKABLE;
×
1042
    else
NEW
1043
      return CHAR_HILITE_INNOCENT;
×
NEW
1044
  case Core::NpcTemplate::EVIL:
×
NEW
1045
    return CHAR_HILITE_MURDERER;
×
1046
  }
NEW
1047
  return CHAR_HILITE_ATTACKABLE;
×
1048
}
1049

1050
unsigned short NPC::name_color( const Character* seen_by ) const
40✔
1051
{
1052
  if ( Core::settingsManager.repsys_cfg.Hooks.NameColor )
40✔
1053
  {
1054
    NPC* t_amy = const_cast<NPC*>( this );
×
1055
    Character* t_bob = const_cast<Character*>( seen_by );
×
1056
    int hook_color = Core::settingsManager.repsys_cfg.Hooks.NameColor->call_long(
×
1057
        t_amy->make_ref(), t_bob->make_ref() );
×
1058
    if ( hook_color != -1 )
×
1059
      return (unsigned short)hook_color;
×
1060
  }
1061

1062
  if ( Core::settingsManager.ssopt.invul_tag == 2 )
40✔
1063
  {
1064
    if ( this->invul() )
×
1065
      return Core::settingsManager.repsys_cfg.NameColoring.Invulnerable;
×
1066
  }
1067
  if ( master() )
40✔
1068
  {
1069
    return Core::RepSystem::name_color( seen_by, master() );
18✔
1070
  }
1071

1072
  switch ( template_->alignment )
22✔
1073
  {
1074
  case Core::NpcTemplate::NEUTRAL:
22✔
1075
    return Core::settingsManager.repsys_cfg.NameColoring.Attackable;
22✔
NEW
1076
  case Core::NpcTemplate::GOOD:
×
NEW
1077
    if ( is_murderer() )
×
NEW
1078
      return Core::settingsManager.repsys_cfg.NameColoring.Murderer;
×
NEW
1079
    else if ( is_criminal() )
×
NEW
1080
      return Core::settingsManager.repsys_cfg.NameColoring.Criminal;
×
1081
    else
NEW
1082
      return Core::settingsManager.repsys_cfg.NameColoring.Innocent;
×
NEW
1083
  case Core::NpcTemplate::EVIL:
×
NEW
1084
    return Core::settingsManager.repsys_cfg.NameColoring.Murderer;
×
1085
  }
1086

NEW
1087
  return Core::settingsManager.repsys_cfg.NameColoring.Attackable;
×
1088
}
1089

1090
///
1091
/// To Set Amy Criminal (For a LevelOfOffense)
1092
///
1093
///  If the LevelOfOffense is 0,
1094
///     clear the CriminalTimer
1095
///  Else
1096
///     Set her Criminal Timer for (LevelOfOffense * CriminalFlagInterval) seconds
1097
///
1098

1099
void Character::make_criminal( int level )
×
1100
{
1101
  set_dirty();
×
1102
  bool was_criminal = is_criminal();
×
1103

1104
  if ( level )
×
1105
  {
1106
    Core::polclock_t timeout_at =
1107
        Core::polclock() + level *
×
1108
                               static_cast<Core::polclock_t>(
×
1109
                                   Core::settingsManager.repsys_cfg.General.CriminalFlagInterval ) *
×
1110
                               Core::POLCLOCKS_PER_SEC;
×
1111

1112
    restart_criminal_timer( timeout_at );
×
1113
    Core::RepSystem::schedule_repsys_task( this, timeout_at + 1 );
×
1114
  }
1115
  else
1116
  {
1117
    clear_criminal_timer();
×
1118
    Core::RepSystem::schedule_repsys_task( this, Core::polclock() - 1 );
×
1119
  }
1120

1121
  if ( !orphan() && was_criminal != is_criminal() )
×
1122
  {
1123
    // Changed to update!
1124
    on_criminal_changed();
×
1125
  }
1126
}
×
1127

1128
void Character::make_murderer( bool newval )
1✔
1129
{
1130
  bool refresh = ( mob_flags_.get( MOB_FLAGS::MURDERER ) != newval );
1✔
1131

1132
  set_dirty();
1✔
1133
  mob_flags_.change( MOB_FLAGS::MURDERER, newval );
1✔
1134

1135
  if ( !orphan() && refresh )
1✔
1136
  {
1137
    // Changed to update!
1138
    on_murderer_changed();
1✔
1139
  }
1140
  Core::RepSystem::schedule_repsys_task( this, Core::polclock() - 1 );
1✔
1141
}
1✔
1142

1143
void Character::make_aggressor_to( Character* chr )
×
1144
{
1145
  Core::polclock_t aggr_timeout_at =
1146
      Core::polclock() +
×
1147
      Core::settingsManager.repsys_cfg.General.AggressorFlagTimeout * Core::POLCLOCKS_PER_SEC;
×
1148
  restart_aggressor_timer( chr, aggr_timeout_at );
×
1149

1150
  // Changed to update!
1151
  on_aggressor_changed();
×
1152

1153
  Core::RepSystem::schedule_repsys_task( this, aggr_timeout_at + 1 );
×
1154
}
×
1155

1156
void Character::make_lawfullydamaged_to( Character* chr )
×
1157
{
1158
  Core::polclock_t aggr_timeout_at =
1159
      Core::polclock() +
×
1160
      Core::settingsManager.repsys_cfg.General.AggressorFlagTimeout * Core::POLCLOCKS_PER_SEC;
×
1161
  restart_lawfully_damaged_timer( chr, aggr_timeout_at );
×
1162

1163
  // Changed to update!
1164
  on_lawfullydamaged_changed();
×
1165

1166
  Core::RepSystem::schedule_repsys_task( this, aggr_timeout_at + 1 );
×
1167
}
×
1168

1169
// add serial to Bob's ToBeReportable list
1170
void Character::add_to_be_reportable( u32 repserial )
1✔
1171
{
1172
  set_dirty();
1✔
1173
  to_be_reportable_.insert( repserial );
1✔
1174
}
1✔
1175
void Character::clear_to_be_reportables()
39✔
1176
{
1177
  set_dirty();
39✔
1178
  to_be_reportable_.clear();
39✔
1179
}
39✔
1180
void Character::commit_to_reportables()
72✔
1181
{
1182
  set_dirty();
72✔
1183
  Core::polclock_t now = Core::polclock();
72✔
1184

1185
  ToBeReportableList::iterator itr = to_be_reportable_.begin(), end = to_be_reportable_.end();
72✔
1186
  for ( ; itr != end; ++itr )
73✔
1187
  {
1188
    reportable_t rt;
1189
    rt.serial = ( *itr );
1✔
1190
    rt.polclock = now;
1✔
1191
    reportable_.insert( rt );
1✔
1192
  }
1193

1194
  to_be_reportable_.clear();
72✔
1195
}
72✔
1196
void Character::clear_reportable( u32 repserial, Core::polclock_t when )
×
1197
{
1198
  set_dirty();
×
1199
  reportable_t rt;
1200
  rt.serial = repserial;
×
1201
  rt.polclock = when;
×
1202
  reportable_.erase( rt );
×
1203
}
×
1204
void Character::clear_my_aggressors()
72✔
1205
{
1206
  // we don't actually have a list of aggressors.
1207
  ToBeReportableList::iterator itr = to_be_reportable_.begin(), end = to_be_reportable_.end();
72✔
1208
  for ( ; itr != end; ++itr )
73✔
1209
  {
1210
    u32 repserial = ( *itr );
1✔
1211
    Character* aggressor = Core::system_find_mobile( repserial );
1✔
1212
    if ( aggressor != nullptr )
1✔
1213
    {
1214
      aggressor->remove_as_aggressor_to( this );
1✔
1215
    }
1216
  }
1217
}
72✔
1218
void Character::remove_as_aggressor_to( Character* chr )
1✔
1219
{
1220
  Core::CharacterRef ref( chr );
1✔
1221
  aggressor_to_.erase( ref );
1✔
1222
  if ( chr->client != nullptr )
1✔
1223
  {
1224
    send_create_mobile_if_nearby_cansee( chr->client, this );
×
1225
  }
1226
  if ( client != nullptr )
1✔
1227
  {
1228
    send_create_mobile_if_nearby_cansee( client, chr );
×
1229
  }
1230
}
1✔
1231
void Character::clear_my_lawful_damagers()
72✔
1232
{
1233
  // we don't actually have a list of aggressors.
1234
  ToBeReportableList::iterator itr = to_be_reportable_.begin(), end = to_be_reportable_.end();
72✔
1235
  for ( ; itr != end; ++itr )
73✔
1236
  {
1237
    u32 repserial = ( *itr );
1✔
1238
    Character* damager = Core::system_find_mobile( repserial );
1✔
1239
    if ( damager != nullptr )
1✔
1240
    {
1241
      damager->remove_as_lawful_damager( this );
1✔
1242
    }
1243
  }
1244
}
72✔
1245

1246
void Character::remove_as_lawful_damager( Character* chr )
1✔
1247
{
1248
  Core::CharacterRef ref( chr );
1✔
1249
  lawfully_damaged_.erase( ref );
1✔
1250

1251
  if ( chr->client != nullptr )
1✔
1252
  {
1253
    send_create_mobile_if_nearby_cansee( chr->client, this );
×
1254
  }
1255
  if ( client != nullptr )
1✔
1256
  {
1257
    send_create_mobile_if_nearby_cansee( client, chr );
×
1258
  }
1259
}
1✔
1260

1261
// Keep these as separate functions if there will be in the future something specific for them
1262
// For now they are just copies of each other
1263

1264
void Character::on_criminal_changed()
×
1265
{
1266
  if ( this->client )
×
1267
    send_move( this->client, this );
×
1268
  send_create_mobile_to_nearby_cansee( this );
×
1269
}
×
1270

1271
void Character::on_murderer_changed()
1✔
1272
{
1273
  if ( this->client )
1✔
1274
    send_move( this->client, this );
×
1275
  send_create_mobile_to_nearby_cansee( this );
1✔
1276
}
1✔
1277

1278
void Character::on_aggressor_changed()
×
1279
{
1280
  if ( this->client )
×
1281
    send_move( this->client, this );
×
1282
  send_create_mobile_to_nearby_cansee( this );
×
1283
}
×
1284

1285
void Character::on_lawfullydamaged_changed()
×
1286
{
1287
  if ( this->client )
×
1288
    send_move( this->client, this );
×
1289
  send_create_mobile_to_nearby_cansee( this );
×
1290
}
×
1291
}  // namespace Mobile
1292
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc