Yer both right...what I was attempting to do was handle the
weirdness of .357 and .38 being roughly the same caliber
while at the same time calculating integer damage. That
was the point of the multiplication by 0.10, but sadly I
goofed and rather than apply that calculation to a temporary
variable, I changed the pistol's Caliber permanently. Ewps!
The following code should behave more sanely. Note especially
the debug statements. If you enable debugging for yourself
(see:
help debug ), you'll get a report of what the pistol
is calculating at a given point. Debug statements are a very
handy tool for when your code is doing something you
don't understand.
Note that this code isn't perfect, it's just a quick rewrite to
better illustrate the mechanics of what's going on.
/lib/firearm.c#include "include/firearm.h"
#include <lib.h>
#include <damage_types.h>
#include <dirs.h>
inherit LIB_STORAGE;
inherit LIB_LOAD;
private int MaxAmmo, Millimeter, AmmoSize;
private string FirearmType, AmmoType;
private string AmmoFile, firearm_name;
private float Caliber;
private string *namen;
private string *ammonamen;
private int loaded, rounds;
private int shells, magnum;
private int mag,cloned;
private int autohit;
private int dam, last_shot;
static void create(){
string *s_save, *a_save;
::create();
s_save = storage::GetSave();
a_save = s_save;
AddSave( a_save );
AddSave( ({ "loaded", "rounds", "shells" , "mag" , "cloned" }) );
MaxAmmo=6;
AmmoFile="/domains/default/obj/round";
FirearmType="revolver";
AmmoType="round";
loaded=1;
rounds=0;
}
void init(){
object ob;
object *inv;
::init();
//add_action("startLoad","load");
//add_action("startUnload","unload");
this_object()->CalculateAmmoSize();
namen=this_object()->GetId();
if(FirearmType=="revolver"
&& !present("cylinder",this_object())){
new("/lib/cylinder")->eventMove(this_object());
}
if(FirearmType=="revolver" && !cloned){
cloned=1;
ob=present("cylinder", this_object());
inv=all_inventory(ob);
filter(inv, (: this_object()->InitRevolver($1->GetId()) :) );
}
if(FirearmType=="auto" && !present("clip",this_object()) ){
mag=0;
loaded=0;
rounds=0;
}
}
string SetFirearmName(string str){
if(str) firearm_name = str;
return firearm_name;
}
string GetFirearmName(){
if(firearm_name) return firearm_name;
return GetKeyName();
}
int InitRevolver(string *arr){
if(member_array("round",arr) != -1){
rounds++;
return 1;
}
if(member_array("shell",arr) != -1){
shells++;
return 1;
}
}
mixed CanGetFrom(object who, object item){
return "It doesn't work that way. Try unloading it.";
}
mixed CanPutInto(object who, object what){
return "It doesn't work that way. Try loading the "+GetFirearmName()+" with something.";
}
int CanReceive(object ob){
string *idarray;
if(FirearmType=="revolver"){
if(rounds == MaxAmmo){
write("It is already fully loaded.");
return 1;
}
}
if(FirearmType != "auto" && ob->GetKeyName() != "revolver cylinder"){
write("This "+GetFirearmName()+" only receives bullets.");
return 0;
}
idarray=ob->GetId();
if(FirearmType=="auto" && member_array("magazine",idarray) == -1){
write("This "+GetFirearmName()+" only receives ammunition clips.");
return 0;
}
if(FirearmType=="auto" && ob->GetMillimeter() != this_object()->GetMillimeter() ){
write("That is not the correct ammunition clip size.");
return 0;
}
if(FirearmType=="auto" && ob->GetCaliber() != this_object()->GetCaliber() ){
write("That is not the correct ammunition clip caliber.");
return 0;
}
if(FirearmType=="auto" && ob->GetAmmoType() != this_object()->GetAmmoType() ){
write("That is not the correct ammunition clip type.");
return 0;
}
if(FirearmType=="auto" && mag){
write("The "+GetFirearmName()+" is already loaded.");
return 0;
}
if(FirearmType=="auto"){
mag=1;
rounds=sizeof(all_inventory(ob));
}
return 1;
}
int CanRelease(object ob){
if(ob->GetKeyName()=="revolver cylinder"){
return 0;
}
return 1;
}
mixed eventShoot(object ob, mixed target){
object cible;
object shell;
object *obs;
if(objectp(target)){
cible = target;
}
else {
obs = filter(get_livings(environment(this_player())),
(: answers_to($(target), $1) :));
if(!sizeof(obs)) cible = present(target,environment(this_player()));
else cible = obs[0];
}
if(cible) target = cible->GetName();
else {
write("It seems there's a problem targeting "+target+".");
return 1;
}
if(!rounds || rounds == 0){
write("Your weapon is not loaded.\n");
say(environment(this_object())->GetName()+" tries to shoot "+capitalize(target)+" with an unloaded weapon.\n");
return 1;
}
write("You shoot at "+capitalize(target)+"!\n");
say(environment(this_object())->GetName()+" shoots at "+capitalize(target)+"!\n");
if(cible) tell_object(cible, environment(this_object())->GetName()+
" shoots at you!\n");
this_object()->eventFire(target);
if(FirearmType=="auto"){
shell = new(LIB_SHELL);
if(!shell) return 1;
shell->SetFirearmType(GetFirearmType());
shell->SetCaliber(GetCaliber());
shell->eventMove(environment(environment(this_object())));
}
return 1;
}
int eventFire(mixed str){
object ob;
object *obs;
int tempclass, i, dex;
int TorsoNum, NumLimbs;
mixed dexmap;
string tempshort,templong;
string *limbarr;
int limbhit;
string limbname;
string s1,s2;
rounds--;
if(this_object()->GetFirearmType() == "auto"){
if(first_inventory(present("magazine",this_object())) ){
first_inventory(present("magazine",this_object()))->eventDestruct();
present("magazine",this_object())->MinusAmmo(1);
}
else rounds=0;
}
if(this_object()->GetFirearmType() == "revolver"){
shells++;
ob=present("cylinder",this_object());
if(present("round",ob)) present("round",ob)->eventDestruct();
new("/lib/shell")->eventMove(ob);
}
if(rounds <= 0) loaded=0;
ob = 0;
if(objectp(str)) ob = str;
else obs = filter(get_livings(environment(this_player())),
(: answers_to($(str), $1) :));
if(!ob && !sizeof(obs)) ob = present(str,environment(this_player()));
else if(!ob) ob = obs[0];
if(creatorp(ob)){
write(ob->GetName()+" catches your bullet in "+possessive(ob)+" teeth.\n");
say(ob->GetName()+" catches the bullet in "+possessive(ob)+" teeth.\n");
autohit=0;
return 1;
}
if(ob && !living(ob) && base_name(ob) != LIB_CORPSE){
tell_room(environment(environment(this_object())),
"The bullet smashes into "+lower_case(ob->GetShort())+"!\n");
if(!sscanf(ob->GetLong(),"%sIt has been damaged by gun%s",s1,s2)){
tempclass=ob->GetClass();
if(tempclass) ob->SetClass(tempclass/2);
tempshort=ob->GetShort();
tempshort = "a damaged "+remove_article(tempshort);
ob->SetShort(tempshort);
templong=ob->GetLong();
if(sscanf(templong,"%s\n\n%s",s1,s2) >=1){
templong=s1+" It has been damaged by gunfire.\n\n";
}
else
templong += " It has been damaged by gunfire.";
ob->SetLong(templong);
return 1;
}
tempclass=ob->GetClass();
if(tempclass) ob->SetClass(tempclass/2);
return 1;
}
i = random(100);
if(!creatorp(environment())){
dex = environment(this_object())->GetStatLevel("coordination");
dex += (environment(this_object())->GetStatLevel("luck") / 3);
if(environment(this_object())->GetSkillLevel("firearms") < 10){
int now = time();
if(last_shot == now) dex -= 100;
else if((now - last_shot) < 2) dex -= 50;
}
}
else dex = 200;
last_shot = time();
if((ob && living(ob)) && (i < dex || autohit==1)){
NumLimbs=sizeof(ob->GetLimbs());
TorsoNum=member_array(ob->GetTorso(),ob->GetLimbs());
i=random(100);
if(i < 50) limbhit=TorsoNum;
else limbhit=random(NumLimbs);
limbarr=ob->GetLimbs();
limbname=limbarr[limbhit];
tell_room(environment(environment(this_object())),"The bullet smashes into "+
capitalize(str)+"'s "+limbname+"!\n",ob);
tell_object(ob,"The bullet smashes into your "+limbname+"!\n");
ob->AddLead("gunshot_wounds", 1);
ob->SetAttack(this_agent());
if(!present("firearms_wound",ob)){
new(LIB_WOUND)->eventMove(ob);
}
if(Caliber){
float tmp;
int extradam = this_object()->GetMagnum();
debug("extradam: "+extradam);
if(to_float(Caliber) < 1.00) Caliber = to_float(Caliber) * 100.00;
debug("Caliber: "+Caliber);
if(Caliber > 99) tmp = to_float(Caliber) * 0.10;
else tc(Caliber +" is not larger than 99");
debug("tmp: "+tmp);
dam = to_int(tmp);
debug("pre magnum dam: "+dam);
if(extradam) dam += (random(extradam/2) + extradam/2);
debug("post magnum dam: "+dam);
}
if(Millimeter){
dam = Millimeter;
dam *= random(10);
}
if(!dam) dam = 7;
debug("pre modifiers dam: "+dam);
dam += random(environment(this_object())->GetStatLevel("coordination"));
debug("post coordination check dam: "+dam);
dam += environment(this_object())->GetSkillLevel("projectile attack");
debug("post skill level check dam: "+dam);
dam -= random(ob->GetStatLevel("luck"));
debug("post luck check on target dam: "+dam);
dam -= random(ob->GetSkillLevel("projectile defense"));
debug("post skill level check on target dam: "+dam);
if(creatorp(this_player())) write("you do "+dam+" points of damage");
ob->eventReceiveDamage(environment(this_object()),(PIERCE), dam, 0, limbname);
if(!ob->GetInCombat()){
ob->eventForce("attack "+environment(this_object())->GetKeyName());
}
autohit=0;
return 1;
}
write("Your shot misses its mark.\n");
say(environment(this_object())->GetName()+"'s shot misses its mark.\n");
this_object()->missed_shot();
return 1;
}
int missed_shot(){
object ob,maghere,magstuff;
string str;
int i;
object *inv;
string *arr;
if(environment(environment(this_object()))->GetClimate() != "indoors"){
return 1;
}
inv=all_inventory(environment(environment(this_object())));
i=random(sizeof(inv));
if(living(inv[i])){
tell_room(environment(environment(this_object())), inv[i]->GetName()+" is struck "+
"by the stray bullet!",inv[i]);
tell_object(inv[i],"You are struck by a stray bullet from "+environment(this_object())->GetName()+
"'s gun.\n");
}
if(!living(inv[i])){
arr=explode(inv[i]->GetKeyName(),"");
if(arr[sizeof(arr)-1] =="s"){
tell_room(environment(environment(this_object())),capitalize(inv[i]->GetShort())+" are struck by the stray bullet.");
}
else
tell_room(environment(environment(this_object())),capitalize(inv[i]->GetShort())+" is struck by the stray bullet.");
}
autohit=1;
rounds++;
this_object()->eventFire(inv[i]->GetKeyName());
if(this_object()->GetFirearmType() == "revolver"){
shells--;
present("shell",present("cylinder",this_object()))->eventDestruct();
ob=new("/lib/round");
ob->SetCaliber(this_object()->GetCaliber());
ob->SetMillimeter(this_object()->GetMillimeter());
ob->SetFirearmType(this_object()->GetFirearmType());
ob->SetAmmoType(this_object()->GetAmmoType());
ob->eventMove(present("cylinder",this_object()));
}
else
{
str = "";
maghere=present("magazine",this_object());
if(maghere) magstuff = first_inventory(maghere);
if(maghere && magstuff) str=base_name(magstuff);
if(str && str !="" ) new(str)->eventMove(maghere);
}
return 1;
}
int CalculateAmmoSize(){
float i;
i=this_object()->GetCaliber();
if(i > 0){
if(stringp(i)) sscanf(i,"%d",i);
if(intp(i)) to_float(i);
while(i > 1.0){
i = i*(0.1);
}
i = i*(25.4);
AmmoSize=to_int(i);
dam=AmmoSize*(AmmoSize);
dam *= 3;
return 1;
}
AmmoSize=this_object()->GetMillimeter();
return 1;
}
int ShowRounds(){ environment(this_object())->eventPrint("Firearm has: "+rounds+" rounds.\n");
environment(this_object())->eventPrint("Firearm has: "+shells+" shells.\n");
return 1;
}
int SetAmmo(int i){ rounds=i; return 1; }
int GetAmmo(){ return rounds; }
int GetMag(){ return mag; }
int SetMag(int i){ mag=i; return 1; }
int SetLoaded(int i){ loaded=i; return 1; }
int GetLive(){ return loaded; }
int SetAmmoFile(string str){ AmmoFile=str; return 1; }
int SetAmmoType(string str){ AmmoType=str; return 1; }
int SetFirearmType(string str){ FirearmType=str; return 1; }
int SetMaxAmmo(int x){ MaxAmmo=x; return 1; }
int SetCaliber(int x){ Caliber=x; return 1; }
int SetMillimeter(int x){ Millimeter=x; return 1; }
string GetAmmoType(){ return AmmoType; }
string GetFirearmType(){ return FirearmType; }
int GetMaxAmmo(){ return MaxAmmo; }
int GetCaliber(){ return Caliber; }
int GetMillimeter(){ return Millimeter; }
mixed eventLoad(object ob){
mixed can = CanLoad(this_player());
if(!can || !intp(can)) return 0;
if(!ob || !objectp(ob) || (objectp(ob) && living(ob))){
write("Load "+GetKeyName()+" with what?");
return 1;
}
if(GetFirearmType() == "revolver" && ob && objectp(ob) &&
ob->GetFirearmType() == "revolver" && (base_name(ob) == LIB_ROUND ||
inherits(LIB_ROUND,ob)) && ob->GetCaliber() == GetCaliber() &&
rounds != MaxAmmo){
rounds++;
}
return 1;
}
mixed eventUnload(mixed what){
string n1,s1,s2;
int n2;
mixed can = CanUnload(this_player());
if(!can || !intp(can)) return 0;
if(FirearmType=="auto" && !mag){
write("It's already unloaded.");
return 1;
}
if(mag==1 && environment(this_object()) == this_player()){
this_object()->doMagUnload();
return 1;
}
if(FirearmType=="revolver" &&
environment(this_object()) == this_player()){
if(rounds == 0 && shells == 0){
write("Your "+GetFirearmName()+" is already empty.");
return 1;
}
if(intp(what) && what < 7 && what > 0) true();
else what = "all";
write("You unload your "+GetFirearmName()+".");
this_object()->doRevolverUnload("all",what);
return 1;
}
}
int doMagUnload(){
if(!present("clip",this_object())){
write("The "+GetFirearmName()+" is already empty.");
return 0;
}
write("You unload an ammo clip from your "+GetFirearmName()+".");
say(this_player()->GetName()+" unloads an ammo clip from "+possessive(this_player())+" "+GetFirearmName()+".");
present("clip",this_object())->eventMove(environment(this_object()));
mag=0;
loaded=0;
rounds=0;
return 1;
}
int doRevolverUnload(string what, string num){
int i,n1,n2;
if(sscanf(num,"%d",n1)){
}
if(what=="all"){
n1=shells;
n2=rounds;
}
if(what=="shells" || what=="all"){
i=shells-n1;
while(shells > i){
present("shell",present("revolver cylinder",this_object()))->eventMove(environment(this_object()));
shells--;
}
}
if(what=="rounds" || what=="all"){
if(what != "all") n2=n1;
i=rounds-n2;
while(rounds > i){
present("round",present("revolver cylinder",this_object()))->eventMove(environment(this_object()));
rounds--;
}
}
if(n2 > 0){
string things = "rounds";
if(n2 == 1) things = "round";
write("You unload "+cardinal(n2)+" "+things+" from your "+GetFirearmName()+".");
}
if(n1 > 0){
string things = "shells";
if(n1 == 1) things = "shell";
write("You unload "+cardinal(n1)+" "+things+" from your "+GetFirearmName()+".");
}
say(environment(this_object())->GetName()+" unloads some cartridges from "+
possessive(environment(this_object()))+" revolver.");
return 1;
}
int GetMaxLoaded(){
if(rounds + shells >= MaxAmmo) return 1;
return 0;
}
int GetMagnum(){
return magnum;
}
int SetMagnum(int i){
if(i > 0) magnum = i;
else magnum = 0;
return magnum;
}
It isn't much excuse, but it's worth mentioning that my firearms
code is one of the very earliest pieces of lib coding I ever did,
so you'll likely see some clumsy stuff in there. Definitely unpretty
and could probably use a complete overhaul...but hey, it mostly
works for now

-Crat