1 /* Copyright (C) 2013-2014 Michal Brzozowski (rusolis@poczta.fm)
2 
3    This file is part of KeeperRL.
4 
5    KeeperRL is free software; you can redistribute it and/or modify it under the terms of the
6    GNU General Public License as published by the Free Software Foundation; either version 2
7    of the License, or (at your option) any later version.
8 
9    KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10    even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License along with this program.
14    If not, see http://www.gnu.org/licenses/ . */
15 
16 #include "stdafx.h"
17 
18 #include "ranged_weapon.h"
19 #include "creature.h"
20 #include "level.h"
21 #include "attack.h"
22 #include "view.h"
23 #include "game.h"
24 #include "sound.h"
25 #include "attack_level.h"
26 #include "attack_type.h"
27 #include "skill.h"
28 #include "creature_attributes.h"
29 #include "player_message.h"
30 #include "view_id.h"
31 #include "event_listener.h"
32 #include "vision.h"
33 
SERIALIZE_DEF(RangedWeapon,damageAttr,projectileName,projectileViewId)34 SERIALIZE_DEF(RangedWeapon, damageAttr, projectileName, projectileViewId)
35 SERIALIZATION_CONSTRUCTOR_IMPL(RangedWeapon)
36 
37 RangedWeapon::RangedWeapon(AttrType attr, const string& name, ViewId id)
38     : damageAttr(attr), projectileName(name), projectileViewId(id) {}
39 
fire(WCreature c,Vec2 dir) const40 void RangedWeapon::fire(WCreature c, Vec2 dir) const {
41   CHECK(dir.length8() == 1);
42   c->getGame()->getView()->addSound(SoundId::SHOOT_BOW);
43   int damage = c->getAttr(damageAttr);
44   Attack attack(c, Random.choose(AttackLevel::LOW, AttackLevel::MIDDLE, AttackLevel::HIGH),
45       AttackType::SHOOT, damage, damageAttr, none);
46   const auto position = c->getPosition();
47   auto vision = c->getVision().getId();
48   Position lastPos;
49   for (Position pos = position.plus(dir);; pos = pos.plus(dir)) {
50     lastPos = pos;
51     if (auto c = pos.getCreature()) {
52       c->you(MsgType::HIT_THROWN_ITEM, "the " + projectileName);
53       c->takeDamage(attack);
54       break;
55     }
56     if (pos.stopsProjectiles(vision)) {
57       pos.globalMessage("the " + projectileName + " hits the " + pos.getName());
58       break;
59     }
60   }
61   c->getGame()->addEvent(EventInfo::Projectile{projectileViewId, position, lastPos});
62 }
63 
getDamageAttr() const64 AttrType RangedWeapon::getDamageAttr() const {
65   return damageAttr;
66 }
67