forked from cataclysmbnteam/Cataclysm-BN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
active_item_cache.cpp
124 lines (114 loc) · 4.26 KB
/
active_item_cache.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "active_item_cache.h"
#include <algorithm>
#include <utility>
#include "item.h"
#include "safe_reference.h"
void active_item_cache::remove( const item *it )
{
active_items[it->processing_speed()].remove_if( [it]( const item_reference & active_item ) {
item *const target = active_item.item_ref.get();
return !target || target == it;
} );
if( it->can_revive() ) {
special_items[ special_item_type::corpse ].remove_if( [it]( const item_reference & active_item ) {
item *const target = active_item.item_ref.get();
return !target || target == it;
} );
}
if( it->get_use( "explosion" ) ) {
special_items[ special_item_type::explosive ].remove_if( [it]( const item_reference &
active_item ) {
item *const target = active_item.item_ref.get();
return !target || target == it;
} );
}
}
void active_item_cache::add( item &it, point location )
{
// If the item is alread in the cache for some reason, don't add a second reference
std::list<item_reference> &target_list = active_items[it.processing_speed()];
if( std::find_if( target_list.begin(),
target_list.end(), [&it]( const item_reference & active_item_ref ) {
return &it == active_item_ref.item_ref.get();
} ) != target_list.end() ) {
return;
}
if( it.can_revive() ) {
special_items[ special_item_type::corpse ].push_back( item_reference{ location, it.get_safe_reference() } );
}
if( it.get_use( "explosion" ) ) {
special_items[ special_item_type::explosive ].push_back( item_reference{ location, it.get_safe_reference() } );
}
target_list.push_back( item_reference{ location, it.get_safe_reference() } );
}
bool active_item_cache::empty() const
{
for( std::pair<int, std::list<item_reference>> active_queue : active_items ) {
if( !active_queue.second.empty() ) {
return false;
}
}
return true;
}
std::vector<item_reference> active_item_cache::get()
{
std::vector<item_reference> all_cached_items;
for( std::pair<const int, std::list<item_reference>> &kv : active_items ) {
for( std::list<item_reference>::iterator it = kv.second.begin(); it != kv.second.end(); ) {
if( it->item_ref ) {
all_cached_items.emplace_back( *it );
++it;
} else {
it = kv.second.erase( it );
}
}
}
return all_cached_items;
}
std::vector<item_reference> active_item_cache::get_for_processing()
{
std::vector<item_reference> items_to_process;
for( std::pair<const int, std::list<item_reference>> &kv : active_items ) {
// Rely on iteration logic to make sure the number is sane.
int num_to_process = kv.second.size() / kv.first;
std::list<item_reference>::iterator it = kv.second.begin();
for( ; it != kv.second.end() && num_to_process >= 0; ) {
if( it->item_ref ) {
items_to_process.push_back( *it );
--num_to_process;
++it;
} else {
// The item has been destroyed, so remove the reference from the cache
it = kv.second.erase( it );
}
}
// Rotate the returned items to the end of their list so that the items that weren't
// returned this time will be first in line on the next call
kv.second.splice( kv.second.end(), kv.second, kv.second.begin(), it );
}
return items_to_process;
}
std::vector<item_reference> active_item_cache::get_special( special_item_type type )
{
std::vector<item_reference> matching_items;
for( const item_reference &it : special_items[type] ) {
matching_items.push_back( it );
}
return matching_items;
}
void active_item_cache::subtract_locations( point delta )
{
for( std::pair<const int, std::list<item_reference>> &pair : active_items ) {
for( item_reference &ir : pair.second ) {
ir.location -= delta;
}
}
}
void active_item_cache::rotate_locations( int turns, point dim )
{
for( std::pair<const int, std::list<item_reference>> &pair : active_items ) {
for( item_reference &ir : pair.second ) {
ir.location = ir.location.rotate( turns, dim );
}
}
}