#combat routines, I haven't had a chance to clean these up yet, edit at your own peril. sub attack { my $attacktype=(shift or "swing"); my $enemy=(shift or $enemy); my $client=(shift or $client); my $weapon=weaponfind(); if (&roundcheck){ return; } my $a; unless ($a=&combatcheck){ $outbuffer{$client}.="You must be engaged to something\r\n$prompt"; return; } print "$attacktype\n$a\n"; unless (defined($attack{$attacktype}{$a})){ $outbuffer{$client}.="Can't attack from this range."; my @a=keys %{$attack{$attacktype}}; if (@a==1){ $outbuffer{$client}.=" You must be at $a[0] range"; } else { $outbuffer{$client}.="You must be at "; while (@a){ if (@a==1){ $outbuffer{$client}.="or $a[0]"; }else { $outbuffer{$client}.="$a[0], "; } shift @a; } $outbuffer{$client}.="\r\n$prompt"; } return; } local $attack=\%{$attack{$attacktype}{$a}}; $user{$client}{balance}+=${$attack}{startbal}; $user{$client}{eng}{pos}+=${$attack}{startpos}; my $tohitscript=(${$weapon}{tohitscript} or \&tohit_normal); my $tohit=&{$tohitscript}; $tohit=$tohit*${$attack}{tohit}; my $line.="$desc{$attacktype}[int($tohit)]"; my $defensescript=(${$weapon}{defensescript} or \&defense_normal); my %list=&{$defensescript}; my $last; foreach $a (keys %list){ $last=$a; if ($list{$a}>$tohit){ print "$a successful.$tohit - $list{$a}\r\n"; $outbuffer{$client}.="$a successful.\r\n$prompt"; return; } } print "$last failed $list{$last}\r\n"; $outbuffer{$client}.="$last failed\r\n"; endcombatdisplay($line); } sub defense_normal { my $modifier; my %list; my $tododge; foreach $a (keys %{$user{$enemy}{defense}}) { if (defined(${$attack}{defenses}{$a})){ $modifier=${$attack}{defenses}{$a}; }else { $modifier=1; } if ($modifier==0) { next; } $tododge=$user{$enemy}{dex}+$user{$enemy}{agi}; $tododge+=int(rand(10)); $tododge=$tododge*$modifier; $list{$a}=$tododge; } return %list; } sub tohit_normal { my $tohit; my $total; my $totalcount; foreach $a (keys %{${$attack}{tohitstats}}){ unless (defined($user{$client}{$a})){ print "Error missing stat $a\n"; } $total=$user{$client}{$a}*${$attack}{tohitstats}{$a}; $totalcount++; } print "$total\n$totalcount\n\n\n"; $total=$total/$totalcount; $total=int ($total+rand(${$attack}{tohitrand})); return $total; print "$total\n"; } sub swing { if (&roundcheck){ print "failed roundcheck\n"; return; } local $enemy=$user{$client}{eng}{to}; attack("swing",$enemy, $client); return; my $weapon=weaponfind(); unless ($weapon){ $outbuffer{$client}.="You don't have a weapon\r\n$prompt"; return; } print "myweapon=$weapon"; my $skill; addexp("$item{$weapon}{primary}","weapons", "1",$client); if (defined($user{$client}{exp}{weapons}{$item{$weapon}{primary}}{ranks})){ $skill=$user{$client}{exp}{weapons}{$item{$weapon}{primary}}{ranks}; print "skill=$skill\n"; } else { $skill=1; } $tohit=$skill+$user{$client}{agi}+int(rand(10))+$user{$client}{eng}{pos}; my $line; if (defined($desc{swing}[$tohit])){ $line.=$desc{swing}[$tohit]; } else { $line.="$desc{swing}[-1]"; } $line.=" [name] swing[1s] at [ename] with $item{$weapon}{name}. "; ($tododge, $skill)=dodge($enemy); unless ($tohit>$tododge){ addexp("evasion","survival",$tohit-$skill*3,$enemy); $line.="[ename] dodge[2s] [nameown] blow."; &endcombatdisplay($line); return; } addexp("evasion","survival", 1,$enemy); $tododge=0; ($tododge, $skill)= parry($enemy); unless ($tohit>$tododge){ addexp("parry","weapons",$tohit,$enemy); $line.="[ename] parry[1s]."; &endcombatdisplay($line); return; } if ($tododge){ addexp("parry","weapons",1,$enemy); } $tododge=0; ($tododge,$skill)=shield($enemy); unless ($tohit>$tododge){ addexp("shield","armor",$tohit,$enemy); $line.="[ename] block[1s]."; &endcombatdisplay($line); return; } if ($tododge){ addexp("shield","armor",1,$enemy); } my $exp=10; #add exp now. addexp("$item{$weapon}{primary}","weapons",$exp); addexp("$item{$weapon}{secondary}","weapons",$exp/2); addexp("$item{$weapon}{third}","weapons",$exp/5); print "\nadded exp to $item{$weapon}{primary},$item{$weapon}{secondary},$item{$weapon}{third}\n"; #Weighted random. choose which body part we wish to hit. my $weight=weight(\%{$user{$enemy}{health}}); my $hit=rand_dist($weight); $line.="[name] hit[1s] [enameown] $hit"; print "hit $hit\n"; #will add a sub to calc damage later... opps did that :) calc damage here my $damage=&calcdamage($weapon); print "Doing $damage damage\n"; dodamage($enemy, "$hit", $damage*$item{$weapon}{piercestr}, "pierce"); dodamage($enemy, "$hit", $damage*$item{$weapon}{impactstr}, "blunt"); dodamage($enemy, "$hit", $damage*$item{$weapon}{slicestr}, "slice"); endcombatdisplay($line); if ($user{$enemy}{vitality}<0){ died($enemy, "$user{$enemy}{deathline}", "$user{$enemy}{deathdesc}"); &endcombat; } if ($user{$enemy}{counterscript}){ unless(defined($user{$enemy}{counterscript})){ print "error!!\r\n"; } else { &{$user{$enemy}{counterscript}}($enemy, $client); } } } sub endcombat { my $enemy=(shift or $enemy); delete $user{$client}{eng}{to}; delete $user{$client}{eng}{distance}; } sub calcdamage { #put here for easy modification. just add skills and str and random +/- factor my $weapon=shift; my $dam=$user{$client}{str}; $dam+=$user{$client}{exp}{weapons}{$item{$weapon}{primary}}{ranks}/5; $dam+=$user{$client}{exp}{weapons}{$item{$weapon}{secondary}}{ranks}/10; $dam+=$user{$client}{exp}{weapons}{$item{$weapon}{third}}{ranks}/20; $dam=$dam*3; $dam+=int(rand(($dam/3)*2)-($dam/3)); return $dam; } sub dodamage { #do damage here, bit nasty right now. my $client=shift; my $location=shift; my $damage=shift; my $type=shift; if ($type eq "pierce"){ $user{$client}{vitality}-=$damage*0.7; }elsif ($type eq "blunt") { $user{$client}{vitality}-=$damage*1.3; }else { $user{$client}{vitality}-=$damage; } if (($type eq "pierce") or ($type eq "slice")){ $user{$client}{health}{$location}{hp}-=$damage; } elsif (($type eq "blunt") or $type eq "pierce") { $user{$client}{health}{$location}{inthp}-=$damage; } } sub endcombatdisplay { my $line=shift; my $round=(shift or 1); my $line2=$line; my $line3=$line2; #nasty parsing stuff. my %keys= ( name=>"you", ename=>$user{$enemy}{name}, "1s"=>"", "2s"=>"s", nameown=>"your", enameown=>"$user{$enemy}{name}'s", ); while ($line=~s/\[(.*?)\]/$keys{$1}/is){ print "$1\n"; } %keys= ( name=>"$user{$client}{name}", ename=>"you", "1s"=>"s", "2s"=>"", nameown=>"$user{$client}{name}'s", enameown=>"your", ); $line2=~s/\[(.*?)\]/$keys{$1}/isg; %keys= ( name=>"$user{$client}{name}", ename=>"$user{$enemy}{name}", "1s"=>"s", "2s"=>"s", nameown=>"$user{$client}{name}'s", enameown=>"$user{$enemy}{name}'s", ); $line3=~s/\[(.*?)\]/$keys{$1}/isg; say3("$line3",$client,$enemy,"$line","$line2"); $outbuffer{$client}.="\r\nRoundtime: $round"; $user{$client}{round}+=$round; $outbuffer{$client}.="\r\n$prompt"; print "$line3\n"; } sub parse { my $string=shift; my %hash={shift}; $string=~s/\[(.*?)\]/$keys{$1}/isg; return $string; } sub shield { $enemy=shift; my $shield; foreach $hold (@{$user{$enemy}{hold}}){ if ($user{$enemy}{health}{$hold}{hold}){ if ($item{$user{$enemy}{health}{$hold}{hold}}{shield}) { $shield=$user{$enemy}{health}{$hold}{hold}; print "shield=$shield"; last; } } } if ($shield){ my $skill=($user{$enemy}{exp}{armor}{shield}{ranks} or 1); my $tododge=$skill+$user{$enemy}{reflex}+int(rand(10)); return ($tododge, $skill); } return 0; } sub parry { my $enemy=shift; my $weapon=weaponfind($enemy); if ($item{$weapon}{parry}){ $skill=($user{$enemy}{exp}{weapons}{parry}{ranks} or 1); $tododge=$skill+$user{$enemy}{reflex}+int(rand(12)); return $tododge, $skill } return 0; } sub dodge { my $enemy=shift; my $skill=($user{$enemy}{exp}{survival}{evasion}{ranks} or 1); my $tododge=$skill+$user{$enemy}{agi}+int(rand(10)); return ($tododge,$skill); } sub combatcheck{ my $client=(shift or $client); print "starting check\n"; unless (defined($user{$client}{eng}{to})){ print "no eng\n"; return 0; } my $enemy=$user{$client}{eng}{to}; unless (defined($user{$enemy})){ print "no enemy\n"; &endcombat; return 0; } unless ($user{$enemy}{room} == $user{$client}{room}){ print "wrong rooms\n"; &endcombat; return 0; } if ($user{$enemy}{dead}){ print "is dead\n"; &endcombat; return 0; } print "distance is $user{$client}{eng}{distance}\n"; return $user{$client}{eng}{distance}; if ($user{$client}{eng}{distance} eq "missile"){ return 1; } if ($user{$client}{eng}{distance} eq "pole"){ return 2; } if ($user{$client}{eng}{distance} eq "melee"){ return 3;} } sub weaponfind { my $client=(shift or $client); unless (defined($user{$client}{weapon})){ $user{$client}{weapon}="right hand"; } my $weapon=$user{$client}{health}{$user{$client}{weapon}}{weapon}; unless ($weapon){ $weapon=$user{$client}{health}{$user{$client}{weapon}}{hold}; } unless ($weapon){ return 0; } return $weapon; } sub rand_dist { #choose a weighted random body part to hit... might use this elsewhere as well. my $dist=shift; my $key; my $rand=rand; foreach $key (keys %{$dist}) { return $key if (($rand -= $dist->{$key})<0); } } sub weight { my $weights=shift; my ($total_weight, %dist)=0; foreach (values %$weights){ $total_weight+=$_->{hitchance};} while (my ($key, $values)= each %$weights){ $dist{$key}= $values->{hitchance}/$total_weight; } return \%dist; } return 1;