OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
inventorymenu.cpp
Go to the documentation of this file.
1#include "inventorymenu.h"
2
3#include <Tempest/Painter>
4#include <Tempest/SoundEffect>
5
6#include "utils/string_frm.h"
7#include "world/objects/npc.h"
10#include "world/world.h"
11#include "utils/gthfont.h"
12#include "utils/keycodec.h"
13#include "gothic.h"
14#include "resources.h"
15
16using namespace Tempest;
17
19 Page()=default;
20 Page(const Page&)=delete;
21 virtual ~Page()=default;
22
23 size_t size() const {
24 if(is(nullptr))
25 return 0;
26 size_t ret = 0;
27 auto it = iterator();
28 while(it.isValid()) {
29 ret++;
30 ++it;
31 }
32 return ret;
33 }
34 Inventory::Iterator get(size_t id) const {
35 auto it = iterator();
36 for(size_t i=0; i<id && it.isValid(); ++i)
37 ++it;
38 return it;
39 }
40
41 virtual bool is(const Inventory* i) const { return i==nullptr; }
42 virtual Inventory::Iterator iterator() const { throw std::runtime_error("index out of range"); }
43 };
44
46 InvPage(const Inventory& i):inv(i){}
47
48 bool is(const Inventory* i) const override { return &inv==i; }
49 Inventory::Iterator iterator() const override {
51 }
52
53 const Inventory& inv;
54 };
55
57 TradePage(const Inventory& i):inv(i){}
58
59 bool is(const Inventory* i) const override { return &inv==i; }
60 Inventory::Iterator iterator() const override {
62 }
63
64 const Inventory& inv;
65 };
66
68 RansackPage(const Inventory& i):inv(i){}
69
70 bool is(const Inventory* i) const override { return &inv==i; }
71 Inventory::Iterator iterator() const override {
73 }
74
75 const Inventory& inv;
76 };
77
79 :keycodec(key) {
80 slot = Resources::loadTexture("INV_SLOT.TGA");
81 selT = Resources::loadTexture("INV_SLOT_HIGHLIGHTED.TGA");
82 selU = Resources::loadTexture("INV_SLOT_EQUIPPED.TGA");
83 tex = Resources::loadTexture("INV_BACK.TGA"); // INV_TITEL.TGA
84
85 int invMaxColumns = Gothic::settingsGetI("GAME","invMaxColumns");
86 if(invMaxColumns>0)
87 columsCount = size_t(invMaxColumns); else
88 columsCount = 5;
89
90 setFocusPolicy(NoFocus);
91 setCursorShape(CursorShape::Hidden);
92 takeTimer.timeout.bind(this,&InventoryMenu::onTakeStuff);
93 }
94
97
99 if(state!=State::Closed) {
100 if(state==State::Trade)
101 Gothic::inst().emitGlobalSound("TRADE_CLOSE"); else
102 Gothic::inst().emitGlobalSound("INV_CLOSE");
103 }
104 renderer.reset(true);
105 takeTimer.stop();
106 state = State::Closed;
107 }
108
110 if(pl.isDown() || pl.isMonster() || pl.isInAir() || pl.isSlide() || (pl.interactive()!=nullptr))
111 return;
113 return;
115 pl.stopAnim("");
116 pl.closeWeapon(false);
117 }
118 state = State::Equip;
119 player = &pl;
120 trader = nullptr;
121 chest = nullptr;
122 page = 0;
123 pagePl .reset(new InvPage (pl.inventory()));
124 pageOth.reset();
125 adjustScroll();
126 update();
127
128 Gothic::inst().emitGlobalSound("INV_OPEN");
129 //Gothic::inst().emitGlobalSound("INV_CHANGE");
130 }
131
133 if(pl.isDown())
134 return;
135 state = State::Trade;
136 player = &pl;
137 trader = &tr;
138 chest = nullptr;
139 page = 0;
140 pagePl .reset(new InvPage (pl.inventory()));
141 pageOth.reset(new TradePage(tr.inventory()));
142 adjustScroll();
143 update();
144 Gothic::inst().emitGlobalSound("TRADE_OPEN");
145 }
146
148 if(pl.isDown())
149 return false;
150 auto it = tr.inventory().iterator(Inventory::T_Ransack);
151 if(!it.isValid())
152 return false;
153 state = State::Ransack;
154 player = &pl;
155 trader = &tr;
156 chest = nullptr;
157 page = 0;
158 pagePl .reset(new InvPage (pl.inventory()));
159 pageOth.reset(new RansackPage(tr.inventory()));
160 adjustScroll();
161 update();
162 Gothic::inst().emitGlobalSound("INV_OPEN");
163 return true;
164 }
165
167 if(pl.isDown())
168 return;
169 const bool needToPicklock = ch.needToLockpick(pl);
170 if(!pl.setInteraction(&ch))
171 return;
172
173 if(needToPicklock && !ch.isCracked()) {
174 state = State::LockPicking;
175 } else {
176 state = State::Chest;
177 }
178
179 player = &pl;
180 trader = nullptr;
181 chest = &ch;
182 page = 0;
183 pagePl .reset(new InvPage(pl.inventory()));
184 pageOth.reset(new InvPage(ch.inventory()));
185 adjustScroll();
186 update();
187 }
188
190 return state;
191 }
192
194 return state!=State::Closed;
195 }
196
198 close();
199 player = nullptr;
200 trader = nullptr;
201 chest = nullptr;
202 }
203
204void InventoryMenu::tick(uint64_t /*dt*/) {
205 if(player!=nullptr && (player->isDown() || player->bodyStateMasked()==BS_UNCONSCIOUS)) {
206 close();
207 return;
208 }
209
210 if(state==State::LockPicking) {
211 if(chest->isCracked()) {
212 state = State::Chest;
213 return;
214 }
215 }
216
217 if(state==State::Ransack) {
218 if(trader==nullptr){
219 close();
220 return;
221 }
222
223 if(!trader->isDown()) {
224 close();
225 return;
226 }
227
228 auto it = trader->inventory().iterator(Inventory::T_Ransack);
229 if(!it.isValid())
230 close();
231 }
232
233 if(state==State::Closed) {
234 if(player!=nullptr){
235 if(!player->setInteraction(nullptr))
236 return;
237 player = nullptr;
238 chest = nullptr;
239 }
240
241 page = 0;
242 renderer.reset();
243 pagePl .reset();
244 pageOth.reset();
245 update();
246 }
247 }
248
249void InventoryMenu::processMove(KeyEvent& e) {
250 auto key = keycodec.tr(e);
251 if(key==KeyCodec::Forward)
252 moveUp();
253 else if(key==KeyCodec::Back)
254 moveDown();
255 else if(key==KeyCodec::Left || key==KeyCodec::RotateL)
256 moveLeft(true);
257 else if(key==KeyCodec::Right || key==KeyCodec::RotateR)
258 moveRight(true);
259 }
260
261void InventoryMenu::moveLeft(bool usePage) {
262 auto& sel = activePageSel();
263
264 if(usePage && sel.sel%columsCount==0 && page>0)
265 page--;
266 else if(sel.sel>0)
267 sel.sel--;
268 }
269
270void InventoryMenu::moveRight(bool usePage) {
271 auto& pg = activePage();
272 auto& sel = activePageSel();
273 const size_t pCount = pagesCount();
274
275 if(usePage && ((sel.sel+1u)%columsCount==0 || sel.sel+1u==pg.size() || pg.size()==0) && page+1u<pCount)
276 page++;
277 else if(sel.sel+1<pg.size())
278 sel.sel++;
279 }
280
281void InventoryMenu::moveUp() {
282 auto& sel = activePageSel();
283
284 if(sel.sel>=columsCount)
285 sel.sel -= columsCount;
286 else
287 moveLeft(false);
288 }
289
290void InventoryMenu::moveDown() {
291 auto& pg = activePage();
292 auto& sel = activePageSel();
293
294 if(sel.sel+columsCount<pg.size())
295 sel.sel += columsCount;
296 else
297 moveRight(false);
298 }
299
301 if(state==State::Closed || state==State::LockPicking){
302 e.ignore();
303 return;
304 }
305
306 processMove(e);
307
308 if(keycodec.tr(e)==KeyCodec::Jump) {
309 lootMode = LootMode::Stack;
310 takeTimer.start(200);
311 onTakeStuff();
312 }
313 else if (keycodec.tr(e)==KeyCodec::ActionGeneric || e.key==KeyEvent::K_Return) {
314 onItemAction(Item::NSLOT);
315 }
316 else if((KeyEvent::K_3<=e.key && e.key<=KeyEvent::K_9) || e.key==KeyEvent::K_0) {
317 uint8_t slot = 10;
318 if((KeyEvent::K_3<=e.key && e.key<=KeyEvent::K_9))
319 slot = uint8_t(e.key-KeyEvent::K_0);
320 onItemAction(slot);
321 }
322 else if(e.key==KeyEvent::K_ESCAPE || keycodec.tr(e)==KeyCodec::Inventory){
323 close();
324 }
325 else if(e.key==KeyEvent::K_Space) {
326 lootMode = LootMode::Normal;
327 takeTimer.start(200);
328 onTakeStuff();
329 }
330 else if(e.key==KeyEvent::K_Z) {
331 lootMode = LootMode::Ten;
332 takeTimer.start(200);
333 onTakeStuff();
334 }
335 else if(e.key==KeyEvent::K_X) {
336 lootMode = LootMode::Hundred;
337 takeTimer.start(200);
338 onTakeStuff();
339 }
340
341 adjustScroll();
342 update();
343 }
344
346 if(state==State::LockPicking || state==State::Closed)
347 return;
348 processMove(e);
349 adjustScroll();
350 update();
351 }
352
354 takeTimer.stop();
355 lootMode = LootMode::Normal;
356 }
357
358void InventoryMenu::mouseDownEvent(MouseEvent &e) {
359 if(player==nullptr || state==State::Closed) {
360 e.ignore();
361 return;
362 }
363
364 if(state==State::LockPicking)
365 return;
366
367 if (e.button==MouseEvent::ButtonLeft)
368 onItemAction(Item::NSLOT);
369 else if (e.button==MouseEvent::ButtonRight)
370 close();
371
372 adjustScroll();
373}
374
376 takeTimer.stop();
377 takeCount=0;
378 }
379
381 if(state==State::Closed) {
382 e.ignore();
383 return;
384 }
385
386 if(state==State::LockPicking)
387 return;
388
389 scrollDelta += e.delta;
390 if(scrollDelta>0) {
391 for(int i=0;i<scrollDelta/120;++i)
392 moveUp();
393 scrollDelta %= 120;
394 } else {
395 for(int i=0;i<-scrollDelta/120;++i)
396 moveDown();
397 scrollDelta %= 120;
398 }
399 adjustScroll();
400 }
401
402const World *InventoryMenu::world() const {
403 return Gothic::inst().world();
404 }
405
406size_t InventoryMenu::rowsCount() const {
407 int iy=30+34+70;
408 return size_t((h()-iy-infoHeight()-20)/slotSize().h);
409 }
410
411void InventoryMenu::paintEvent(PaintEvent &e) {
412 if(player==nullptr || state==State::Closed)
413 return;
414 renderer.reset();
415
416 Painter p(e);
417 drawAll(p,*player,DrawPass::Back);
418 }
419
421 if(player==nullptr || state==State::Closed)
422 return;
423
424 Painter p(e);
425 drawAll(p,*player,DrawPass::Front);
426 }
427
428Size InventoryMenu::slotSize() const {
429 const float scale = Gothic::interfaceScale(this);
430 const float cell = float(Gothic::options().inventoryCellSize);
431 return Size(int(cell*scale),int(cell*scale));
432 }
433
434int InventoryMenu::infoHeight() const {
435 const float scale = Gothic::interfaceScale(this);
436 return (Item::MAX_UI_ROWS+2)*int(float(Resources::font(scale).pixelSize()))+int(scale*10)/*padding bottom*/;
437 }
438
439size_t InventoryMenu::pagesCount() const {
440 if(state==State::Chest || state==State::Trade)
441 return 2;
442 return 1;
443 }
444
445const InventoryMenu::Page &InventoryMenu::activePage() {
446 if(pageOth!=nullptr)
447 return *(page==0 ? pageOth : pagePl);
448 if(pagePl)
449 return *pagePl;
450
451 static Page n;
452 return n;
453 }
454
455InventoryMenu::PageLocal &InventoryMenu::activePageSel() {
456 if(pageOth!=nullptr)
457 return (page==0 ? pageLocal[0] : pageLocal[1]);
458 return pageLocal[1];
459 }
460
461void InventoryMenu::onItemAction(uint8_t slotHint) {
462 auto& page = activePage();
463 auto& sel = activePageSel();
464
465 auto it = page.get(sel.sel);
466 if(!it.isValid())
467 return;
468
469 if(state==State::Equip) {
470 const size_t clsId = it->clsId();
471 if(it.isEquipped() && slotHint==Item::NSLOT) {
472 player->unequipItem(clsId);
473 } else {
474 player->useItem(clsId,slotHint,false);
475 auto it2 = page.get(sel.sel);
476 if((!it2.isValid() || it2->clsId()!=clsId) && sel.sel>0)
477 --sel.sel;
478 }
479 }
480 else if(state==State::Chest || state==State::Trade || state==State::Ransack) {
481 lootMode = LootMode::Normal;
482 takeTimer.start(200);
483 onTakeStuff();
484 }
485 }
486
487void InventoryMenu::onTakeStuff() {
488 size_t itemCount = 0;
489 auto& page = activePage();
490 auto& sel = activePageSel();
491 if(sel.sel >= page.size())
492 return;
493 auto it = page.get(sel.sel);
494 if(lootMode==LootMode::Normal) {
495 ++takeCount;
496 itemCount = uint32_t(std::pow(10,takeCount / 10));
497 if(it.count() <= itemCount) {
498 itemCount = uint32_t(it.count());
499 takeCount = 0;
500 }
501 }
502 else if(lootMode==LootMode::Stack) {
503 itemCount = it.count();
504 }
505 else if(lootMode==LootMode::Ten) {
506 itemCount = 10;
507 }
508 else if(lootMode==LootMode::Hundred) {
509 itemCount = 100;
510 }
511
512 if(it.count() < itemCount) {
513 itemCount = it.count();
514 }
515
516 if(state==State::Chest) {
517 if(page.is(&player->inventory())) {
518 player->moveItem(it->clsId(),*chest,itemCount);
519 } else {
520 player->addItem (it->clsId(),*chest,itemCount);
521 }
522 }
523 else if(state==State::Trade) {
524 if(page.is(&player->inventory())) {
525 player->sellItem(it->clsId(),*trader,itemCount);
526 } else {
527 player->buyItem (it->clsId(),*trader,itemCount);
528 }
529 }
530 else if(state==State::Ransack) {
531 if(page.is(&trader->inventory())) {
532 player->addItem(it->clsId(),*trader,itemCount);
533 }
534 }
535 else if(state==State::Equip) {
536 player->dropItem(it->clsId(),itemCount);
537 }
538 adjustScroll();
539 }
540
541void InventoryMenu::adjustScroll() {
542 auto& page = activePage();
543 auto& sel = activePageSel();
544 sel.sel = std::min(sel.sel, std::max<size_t>(page.size(),1)-1);
545 while(sel.sel<sel.scroll*columsCount) {
546 if(sel.scroll<=1){
547 sel.scroll=0;
548 return;
549 }
550 sel.scroll-=1;
551 }
552
553 const size_t hcount=rowsCount();
554 while(sel.sel>=(sel.scroll+hcount)*columsCount) {
555 sel.scroll+=1;
556 }
557 }
558
559void InventoryMenu::drawAll(Painter &p, Npc &player, DrawPass pass) {
560 const int padd = 43;
561
562 int iy=30+34+70;
563
564 if(state==State::LockPicking)
565 return;
566
567 const int wcount = int(columsCount);
568 const int hcount = int(rowsCount());
569
570 if(chest!=nullptr){
571 if(pass==DrawPass::Back)
572 drawHeader(p,chest->displayName(),padd,70);
573 drawItems(p,pass,*pageOth,pageLocal[0],padd,iy,wcount,hcount);
574 }
575
576 if(trader!=nullptr) {
577 if(pass==DrawPass::Back)
578 drawHeader(p,trader->displayName(),padd,70);
579 drawItems(p,pass,*pageOth,pageLocal[0],padd,iy,wcount,hcount);
580 }
581
582 if(state!=State::Ransack) {
583 if(pass==DrawPass::Back)
584 drawGold (p,player,w()-padd-2*slotSize().w,70);
585 drawItems(p,pass,*pagePl,pageLocal[1],w()-padd-wcount*slotSize().w,iy,wcount,hcount);
586 }
587
588 if(pass==DrawPass::Back)
589 drawInfo(p);
590 }
591
592void InventoryMenu::drawItems(Painter &p, DrawPass pass,
593 const Page &inv, const PageLocal& sel, int x0, int y, int wcount, int hcount) {
594 if(state==State::LockPicking)
595 return;
596
597 if(tex!=nullptr && pass==DrawPass::Back) {
598 p.setBrush(*tex);
599 p.drawRect(x0,y,slotSize().w*wcount,slotSize().h*hcount,
600 0,0,tex->w(),tex->h());
601 }
602
603 auto it = inv.iterator();
604 size_t id = 0;
605 for(size_t i=0; it.isValid() && i<sel.scroll*size_t(wcount); ++i) {
606 ++it;
607 ++id;
608 }
609 for(int i=0;i<hcount;++i) {
610 for(int r=0;r<wcount;++r) {
611 const int x = x0 + r*slotSize().w;
612 if(pass==DrawPass::Back) {
613 p.setBrush(*slot);
614 p.drawRect(x,y,slotSize().w,slotSize().h,
615 0,0,slot->w(),slot->h());
616 }
617 if(it.isValid()) {
618 drawSlot(p,pass, it,inv,sel, x,y, id);
619 ++it;
620 ++id;
621 }
622 }
623 y += slotSize().h;
624 }
625 }
626
627void InventoryMenu::drawSlot(Painter &p, DrawPass pass, const Inventory::Iterator &it,
628 const Page& page, const PageLocal &sel,
629 int x, int y, size_t id) {
630 if(!slot)
631 return;
632
633 auto& active = activePage();
634 const float scale = Gothic::interfaceScale(this);
635
636 if(pass==DrawPass::Back) {
637 if((!it.isValid() && id==0) || (id==sel.sel && &page==&active)){
638 p.setBrush(*selT);
639 p.drawRect(x,y,slotSize().w,slotSize().h,
640 0,0,selT->w(),selT->h());
641 }
642
643 if(it.isEquipped() && selU!=nullptr) {
644 p.setBrush(*selU);
645 p.drawRect(x,y,slotSize().w,slotSize().h,
646 0,0,selU->w(),selU->h());
647 }
648
649 const int dsz = (id==sel.sel ? 5 : 0);
650 renderer.drawItem(x-dsz, y-dsz, slotSize().w+2*dsz, slotSize().h+2*dsz, *it);
651 } else {
652 auto fnt = Resources::font(scale);
653
654 if(it.count()>1) {
655 string_frm vint(int(it.count()));
656 auto sz = fnt.textSize(vint);
657 fnt.drawText(p,x+slotSize().w-sz.w-10,
658 y+slotSize().h-10,
659 vint);
660 }
661
662 if(it.slot()!=Item::NSLOT) {
664
665 string_frm vint(int(it.slot()));
666 auto sz = fnt.textSize(vint);
667 fnt.drawText(p,x+10,
668 y+slotSize().h/2+sz.h/2,
669 vint);
670 }
671 }
672 }
673
674void InventoryMenu::drawGold(Painter &p, Npc &player, int x, int y) {
675 if(!slot)
676 return;
677 auto w = world();
678 auto txt = w ? w->script().currencyName() : "";
679 const size_t gold = player.inventory().goldCount();
680 if(txt.empty())
681 txt="Gold";
682
683 string_frm vint(txt," : ",int(gold));
684 drawHeader(p,vint,x,y);
685 }
686
687void InventoryMenu::drawHeader(Painter &p, std::string_view title, int x, int y) {
688 const float scale = Gothic::interfaceScale(this);
689 auto& fnt = Resources::font(scale);
690
691 const int tw = fnt.textSize(title).w;
692 const int th = fnt.textSize(title).h;
693 const int padd = int(8*scale);
694 const int dw = std::max(slotSize().w*2, tw+padd*2);
695 const int dh = int(34*scale);
696
697 if(tex) {
698 p.setBrush(*tex);
699 p.drawRect(x,y,dw,dh, 0,0,tex->w(),tex->h());
700 }
701 if(slot) {
702 p.setBrush(*slot);
703 p.drawRect(x,y,dw,dh, 0,0,slot->w(),slot->h());
704 }
705
706 fnt.drawText(p,x+(dw-tw)/2,y+dh/2+th/2,title);
707 }
708
709void InventoryMenu::drawInfo(Painter &p) {
710 const float scale = Gothic::interfaceScale(this);
711 const int dw = std::min(w(), int(720*scale));
712 const int dh = infoHeight();
713 const int x = (w()-dw)/2;
714 const int y = h()-dh-20;
715
716 auto& pg = activePage();
717 auto& sel = activePageSel();
718
719 auto it = pg.get(sel.sel);
720 if(!it.isValid())
721 return;
722
723 auto& r = *pg.get(sel.sel);
724 if(tex) {
725 p.setBrush(*tex);
726 p.drawRect(x,y,dw,dh,
727 0,0,tex->w(),tex->h());
728 }
729
730 auto& fnt = Resources::font(scale);
731 auto desc = r.description();
732 int tw = fnt.textSize(desc).w;
733
734 fnt.drawText(p,x+(dw-tw)/2,y+int(fnt.pixelSize()),desc);
735
736 for(size_t i=0;i<Item::MAX_UI_ROWS;++i){
737 auto txt = r.uiText(i);
738 int32_t val = r.uiValue(i);
739
740 if(txt.empty())
741 continue;
742
743 if(i+1==Item::MAX_UI_ROWS && state==State::Trade && player!=nullptr && pg.is(&player->inventory())){
744 val = r.sellCost();
745 }
746
747 string_frm vint(val);
748 int tw = fnt.textSize(vint).w;
749
750 fnt.drawText(p, x+20, y+int(i+2)*fnt.pixelSize(), txt);
751 if(val!=0)
752 fnt.drawText(p,x+dw-tw-20,y+int(i+2)*fnt.pixelSize(),vint);
753 }
754
755 const int sz = dh;
756 renderer.drawItem(x+dw-sz-sz/2,y,sz,sz,r);
757 }
758
759void InventoryMenu::draw(Tempest::Encoder<CommandBuffer>& cmd) {
760 renderer.draw(cmd);
761 }
static auto options() -> const Options &
Definition gothic.cpp:496
static float interfaceScale(const Tempest::Widget *w)
Definition gothic.cpp:471
const World * world() const
Definition gothic.cpp:278
static Gothic & inst()
Definition gothic.cpp:249
static int settingsGetI(std::string_view sec, std::string_view name)
Definition gothic.cpp:807
void emitGlobalSound(std::string_view sfx)
Definition gothic.cpp:395
bool isCracked() const
Definition interactive.h:66
Inventory & inventory()
std::string_view displayName() const
bool needToLockpick(const Npc &pl) const
void keyUpEvent(Tempest::KeyEvent &e) override
bool ransack(Npc &pl, Npc &tr)
void keyDownEvent(Tempest::KeyEvent &e) override
void mouseDownEvent(Tempest::MouseEvent &event) override
bool isActive() const
void trade(Npc &pl, Npc &tr)
InventoryMenu(const KeyCodec &key)
void paintEvent(Tempest::PaintEvent &e) override
void tick(uint64_t dt)
void mouseUpEvent(Tempest::MouseEvent &event) override
void keyRepeatEvent(Tempest::KeyEvent &e) override
void draw(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void paintNumOverlay(Tempest::PaintEvent &e)
State isOpen() const
void open(Npc &pl)
void mouseWheelEvent(Tempest::MouseEvent &event) override
void reset(bool full=false)
void draw(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawItem(int x, int y, int w, int h, const Item &item)
bool isEquipped() const
Definition inventory.cpp:23
size_t count() const
Definition inventory.cpp:33
uint8_t slot() const
Definition inventory.cpp:28
bool isValid() const
Definition inventory.cpp:60
@ T_Inventory
Definition inventory.h:31
Iterator iterator(IteratorType t) const
@ MAX_UI_ROWS
Definition item.h:16
@ NSLOT
Definition item.h:16
@ RotateR
Definition keycodec.h:42
@ ActionGeneric
Definition keycodec.h:45
@ RotateL
Definition keycodec.h:41
@ Inventory
Definition keycodec.h:27
@ Forward
Definition keycodec.h:37
Action tr(Tempest::KeyEvent const &e) const
Definition keycodec.cpp:107
Definition npc.h:25
auto weaponState() const -> WeaponState
Definition npc.cpp:3621
void stopAnim(std::string_view ani)
Definition npc.cpp:979
bool isSlide() const
Definition npc.cpp:1041
void moveItem(size_t id, Interactive &to, size_t count=1)
Definition npc.cpp:3294
bool isInAir() const
Definition npc.cpp:1045
void unequipItem(size_t item)
Definition npc.cpp:3482
auto inventory() const -> const Inventory &
Definition npc.h:330
bool isDown() const
Definition npc.cpp:3974
auto interactive() const -> Interactive *
Definition npc.h:294
void dropItem(size_t id, size_t count=1)
Definition npc.cpp:3325
bool closeWeapon(bool noAnim)
Definition npc.cpp:3490
std::string_view displayName() const
Definition npc.cpp:734
void buyItem(size_t id, Npc &from, size_t count=1)
Definition npc.cpp:3306
void useItem(size_t item)
Definition npc.cpp:3470
void sellItem(size_t id, Npc &to, size_t count=1)
Definition npc.cpp:3298
bool setInteraction(Interactive *id, bool quick=false)
Definition npc.cpp:4101
bool isMonster() const
Definition npc.cpp:1227
Item * addItem(size_t id, size_t amount)
Definition npc.cpp:3233
BodyState bodyStateMasked() const
Definition npc.cpp:3161
static const GthFont & font(const float scale)
static const Tempest::Texture2d * loadTexture(std::string_view name, bool forceMips=false)
Definition world.h:31
@ BS_LIE
Definition constants.h:166
@ BS_UNCONSCIOUS
Definition constants.h:176
Inventory::Iterator iterator() const override
bool is(const Inventory *i) const override
InvPage(const Inventory &i)
const Inventory & inv
virtual Inventory::Iterator iterator() const
virtual ~Page()=default
virtual bool is(const Inventory *i) const
Page(const Page &)=delete
Inventory::Iterator get(size_t id) const
size_t size() const
bool is(const Inventory *i) const override
RansackPage(const Inventory &i)
Inventory::Iterator iterator() const override
TradePage(const Inventory &i)
bool is(const Inventory *i) const override
Inventory::Iterator iterator() const override