Results 1 to 10 of 10

Thread: THROWING KNIFE QUESTION

  1. #1

    Default THROWING KNIFE QUESTION

    using the screw driver model - is it possible to convert the throwing knife to a server side throwing screw driver mod?

  2. #2

    Default

    Interesting idea. I have the script plan in my head already. Give me a month or so, and I'll post a script here (likely a trigger, since changing the Papers weapon item might be harder to do).

  3. #3

    Default Throwing Knife MOHAA Mod .pk3

    <><><> Throwing Knife MOHAA Mod <><><>

    Throwing knives from Call of Duty have now been ported into MOHAA, using the static/screwdriver.tik model as the throwing knife. These knives' origins are placed ideally on top of tables when the map loads initially. Since replacing one of the game's inventory weapons (papers or binoculars) proved harder than expected, these throwing knives are spawned in as trigger_use triggers. Lots of math also went into the thrown knives' angles when they impact a wall or the ground. Once impacted, these knives (screwdrivers) will almost be pointing sharp-end-first into the ground/wall even if thrown from very far away. Any knives that are laying around on the map will be moved back to their map-initial origins after 45 seconds. If the player dies, all held knives are dropped to the ground. If the player switches teams, goes to spectator or leaves, all held knives are moved back to their last known location, before also moving back to their map-initial origins after 45 seconds.

    Hold USE + Right-click to throw a knife. Players can pick up and hold up to 3 throwing knives. Knives cannot kill teammates. Any knife that hits an enemy player is an instant-kill.

    <><><> Parameters & Examples <><><>

    Code:
    - Parameters: name, origin, angles, light.
    - Example: exec global/throwingknife.scr k1 ( 65 125 100 ) ( 0 180 0 ) 0
    
    - Each throwing knife must have its own name ("name" cannot be NIL).
    - The "light" parameter specifies whether to initially illuminate the throwing knives with a green light (0 by default). All knives currently flying in the air have a large red light. All knives that were thrown and now sticking to a wall or the ground have a smaller radius green light.
    
    - "level.knife_resettime = 45" seconds by default. This determines how many seconds until a thrown knife resets back to their map-initial origins/angles.
    
    - "level.knife_velocity = 1400" units per second by default. This determines how fast and how far all knives can be thrown (velocity is not randomized).
    
    - An example mohdm1.scr map is given in the .pk3 for testing this mod. Two bunkertables, each with two throwing knives, are found next to the bridge and the monument. The two level variables above can be added to further modify this mod.
    <><><> Known Bugs & FAQ <><><>

    Code:
    A thrown knife sometimes sticks inside of a wall. This cannot be fixed. The setsize in models/static/screwdriver.tik already ensures that only the tip of the screwdriver is sticking inside. However, some walls' actual .bsp solid brushes are slightly deeper within the wall, than the wall's visible textures. The throwing knives' green lights ensure that players can still see them even if they're inside walls.
    
    Very rare hitbox-related issue: a player's size is 30 x 30 x 95 (standing) or 30 x 30 x 55 (crounching). A thrown knife measures 42.5 maximum vector_length units from enemy players before killing them since (30)^2 + (30)^2 = (42.5)^2, but very rarely the knife could stick in mid-air to the edge of a player without killing them. If that's the case: CTRL+F in throwingknife.scr, search for the last "42.5", increase that number a few more units. 
    
    If a knife was thrown but nothing appeared, make sure you have the global/math.scr file.
    
    If a knife was thrown but it went straight through players and walls (didn't touch anything), you have another mod whose models/static/screwdriver.tik is loading after this one. Add a few more Z's to this .pk3's filename, so this mod loads last.
    <><><> <><><>
    Attached Files Attached Files
    Last edited by Searingwolfe; March 6th, 2023 at 09:57 PM. Reason: reuploaded the .pk3, so it's not giving a virus false-positive

  4. #4

    Default

    That's awesome! Good Job.

    What does the screwdriver need so the screwdriver can be added to the player weapons loadout?

    Code:
        	self give "models/weapons/screwdriver.tik"
    if not in the weapons inventory the screwdriver is used along with the current selected weapon - e.g. fire rifle and throw screwdriver simultaneously

  5. #5

    Default

    Quote Originally Posted by Searingwolfe View Post
    <><><> Throwing Knife MOHAA Mod <><><>
    I want to test it but my antivirus is detecting the throwingknife.scr script as a trojan
    Can you repost it?


  6. #6

    Default

    Not sure if the screwdriver throwing knife can be added to players' inventory. Only way is to have all players spawn with a throwing knife initially. I can add a script that spawns everyone with at least 1 throwing knife though if that's what you need.

    For the throwingknife.scr. Yes I did notice that Windows 10 gives me "are you sure you want to open this" errors (windows 10 related issues for .scr files opening in notepad), but there's literally nothing in the .scr file to cause a virus. The standalone .scr file is posted below:

    Code:
    main local.name local.origin local.angles local.light local.thrown: // global/throwingknife.scr
    
    	if(local.thrown != 1) // run one time after map loads.
    	{
    		level.knife_origin[local.name] = local.origin
    		level.knife_angles[local.name] = local.angles
    
    		if(local.light == 1) { level.knife_light[local.name] = 1 }
    		if(level.knife_resettime == NIL || level.knife_resettime <= 0) { level.knife_resettime = 45 }
    		if(level.knife_velocity == NIL || level.knife_velocity <= 0) { level.knife_velocity = 1400 }
    	}
    	local.trigger = spawn trigger_use
    	local.trigger model "static/screwdriver.tik" 
    	local.trigger.origin = local.origin
    	local.trigger.angles = local.angles
    	local.trigger setsize ( -30 -30 -30 ) ( 30 30 30 )
    	local.trigger.angles = ( 0 90 -45 )
    	local.trigger.scale = 2
    	local.trigger show
    	if(local.light == 1) { local.trigger light 0 1 0 35 }
    	local.trigger.name = local.name
    
    	local.trigger setthread pickup
    
    	if(local.thrown == 1) { local.trigger thread resettimer local.name level.knife_light[local.name] }
    	waitframe
    	local.trigger.angles = local.angles // sometimes, angles do not update unless a waitframe occurs first
    end
    
    pickup:
    
    	self nottriggerable
    	local.player = parm.other
    
    	if(local.player.knivesheld == NIL) { local.player.knivesheld = 0 }
    	local.player.knifename[local.player.knivesheld] = self.name // all knives's names are stored in "knifename" array.
    	local.player.knivesheld++
    
    	if(self != NULL && local.player.knivesheld <= 3) 
    	{
    		self message ("*** Knives held: " + local.player.knivesheld + " ***")
    		local.originold = self.origin
    		local.anglesold = self.angles
    
    		if(local.player.knivesheld == 1) { local.player thread give_knife self.name local.originold local.anglesold; local.player iprint ("Hold USE + Right-click to throw a knife.") }
    		if(local.player.knivesheld == 2) { local.player thread scan_player2 self.name local.originold local.anglesold }		
    		if(local.player.knivesheld == 3) { local.player thread scan_player3 self.name local.originold local.anglesold }
    
    		self nottriggerable // must be nottriggerable before any waitframes, otherwise players can grab 4+ nearby knives by pressing USE key only once, deleting all the extra knives.
    		self hide
    		self.remove = 1
    	}
    	if(self != NULL && local.player.knivesheld > 3) 
    	{
    		local.player.knivesheld = 3
    		local.player iprint ("Cannot hold more than 3 throwing knives.")
    	}
    
    	if(self != NULL && self.remove != 1) { self triggerable; end }
    	waitframe			     // waitframe is placed at the end of "pickup" after doing everything else, so unwanted extra knives don't spawn.
    	if(self.remove == 1) { self remove } // waitframe also allows trigger's message to print first, before trigger is removed.
    end
    
    give_knife local.name local.originold local.anglesold:
    
    	if(self.scanplayer == 1) { end } // make sure no unwanted extra knives are spawned in.
    	self.scanplayer = 1
    
    	self attachmodel models/static/screwdriver.tik "Bip01 L Thigh" 1 ("knife_1" + self.entnum) 1 -1 -1 -1 -1 ( 0 0 -6 ) //( -up +down, +forward -backward, +right -left )
    	$("knife_1" + self.entnum).angles = ( 0 180 20 )
    
    	self waitthread scan_player local.name local.originold local.anglesold
    
    	if(self != NULL) 
    	{
    		self.scanplayer = 0; self.knivesheld = 0; self.knifename[0] = NIL; self.knifename[1] = NIL; self.knifename[2] = NIL
    		if($("knife_1" + self.entnum) != NULL) { $("knife_1" + self.entnum) remove }
    	}
    end
    
    scan_player local.name local.originold local.anglesold:
    	
    	local.team = self.dmteam
    	while(isalive self && self != NULL && self.knivesheld > 0 && self.dmteam == local.team)
     	{
    		if(self != NULL && (self.useheld != 1 || self.fireheld != 1)) { local.holding = 0 }
    
    		while(isalive self && self != NULL && local.holding != 1 && self.useheld == 1 && self.fireheld == 1 && self.knivesheld > 0 && self.dmteam == local.team)
    		{
    			if(self != NULL && self.knivesheld >= 1 && self.knivesheld <= 3) { self thread throw_knife } // slowed down slightly by wait 0.1
    			wait 0.1
    			local.holding = 1
    			break
    		}
      		waitframe
     	}	
    	if(self == NULL) { goto main local.name local.originold local.anglesold 1 1 } 		   // "goto" ends this thread immediately, if player left or switched teams.
    	if(self.dmteam != local.team) { goto main local.name local.originold local.anglesold 1 1 } // isolate and run self==NULL if-statement first, to avoid "applied to NULL listener" console error.
    
    	local.r = randomint(360)
    	local.anglesrandom = self.angles + ( 0 local.r 0 )
    	if(self != NULL && !isalive self) { thread main local.name self.origin local.anglesrandom 1 1 } // if player dies, randomize all dropped knives' angles; looks like multiple knives are on the ground.
    end
    
    scan_player2 local.name local.originold local.anglesold: // need 3 separate "scan_player" threads, so all held knives can reset to their map-inital origins/angles.
    
    	if(self.scanplayer2 == 1) { end }
    	self.scanplayer2 = 1
    	
    	local.team = self.dmteam
    	while(isalive self && self != NULL && self.knivesheld > 0 && self.dmteam == local.team) { waitframe }
    
    	if(self != NULL) { self.scanplayer2 = 0 }
    
    	if(self == NULL) { goto main local.name local.originold local.anglesold 1 1 }
    	if(self.dmteam != local.team) { goto main local.name local.originold local.anglesold 1 1 } // isolate and run self==NULL if-statement first, to avoid "applied to NULL listener" console error.
    
    	local.r = randomint(360)
    	local.anglesrandom = self.angles + ( 0 local.r 0 )
    	if(self != NULL && !isalive self) { thread main local.name self.origin local.anglesrandom 1 1 }
    end
    
    scan_player3 local.name local.originold local.anglesold:
    
    	if(self.scanplayer3 == 1) { end }
    	self.scanplayer3 = 1
    	
    	local.team = self.dmteam
    	while(isalive self && self != NULL && self.knivesheld > 0 && self.dmteam == local.team) { waitframe }
    
    	if(self != NULL) { self.scanplayer3 = 0 }
    
    	if(self == NULL) { goto main local.name local.originold local.anglesold 1 1 }
    	if(self.dmteam != local.team) { goto main local.name local.originold local.anglesold 1 1 } // isolate and run self==NULL if-statement first, to avoid "applied to NULL listener" console error.
    
    	local.r = randomint(360)
    	local.anglesrandom = self.angles + ( 0 local.r 0 )
    	if(self != NULL && !isalive self) { thread main local.name self.origin local.anglesrandom 1 1 }
    end
    
    throw_knife:
    
    	self.knivesheld--
    	local.name = self.knifename[self.knivesheld]
    	self.knifename[self.knivesheld] = NIL
    
    	local.fwd_vec = angles_toforward self.viewangles // fwd_vec[2] = 0 when player looks horizontal, -0.999 looking down, 0.999 looking up.
    
    	if(local.fwd_vec[2] <= 0) { local.height = local.fwd_vec[2] * 60 } // when player is looking down and falling, the knife can get stuck to the player's head.
    	if(local.fwd_vec[2] > 0) { local.height = 0 }			   // if looking vertically down, the knife's height will start a max of 60 units lower initially. 
    
    	local.sin = (waitthread global/math.scr::sine self.angles[1]) * 25   // always spawn the knife 25 units in front of the player's eyes.
    	local.cos = (waitthread global/math.scr::cosine self.angles[1]) * 25 	
    	local.origin = self gettagposition "eyes bone" // Bip01 Head works too.
    
    	local.knife = spawn script_model
    	local.knife model "static/screwdriver.tik"
    	local.knife.origin = local.origin + ( local.cos local.sin 25 ) + ( 0 0 local.height )
    	local.knife.angles = self.angles + ( 90 0 0 )
    	local.knife light 1 0 0 75
    	local.knife.scale = 2
    	local.knife.rotate = 1
    	local.knife solid
    	local.knife physics_on    // need this for gravity and waittill touch to work.
    	//local.knife gravity 1.2 // keep this commented out for game default gravity.
    
    	local.knife.velocity = (angles_toforward self.viewangles) * level.knife_velocity
    
    	local.anglesold = self.viewangles + ( 180 0 0 ) // begin throwing the knife, sharp end facing vertically down.
    	local.anglesoldinv = self.viewangles
    	local.knife thread rotate
    	local.knife thread flytimer
    	local.knife waittill touch
    	
    	local.knife.velocity = ( 0 0 0 ) // velocity = 0 works, but gives a "cannot cast integer to vector" console error.
    
    	for(local.i = 1; local.i <= $player.size; local.i++)
    	{
    		$player[local.i].originxy = ( $player[local.i].origin[0] $player[local.i].origin[1] 0 ) // check if knife's XY origin vector length is < 42.5 units from an enemy player's XY origin, prevents knife floating in air.
    		local.knife.originxy = ( local.knife.origin[0] local.knife.origin[1] 0 )		// players' origins start at their feet. players' physical size = 30 x 30 x 95. Maximum length is hypotenuse of 30 x 30.
    													// 30^2 + 30^2 = (squareroot(1800))^2 = (42.4254)^2, so 42.5 = max possible distance for knife to touch a player.
    		local.position = $player[local.i] getposition
    		local.playerheight = 95
    		if(local.position == crouching) { local.playerheight = 55 } // lower players' "hitboxes" if they're crouching.
    
    		if(vector_length(local.knife.originxy - $player[local.i].originxy) < 42.5 && local.knife.origin[2] - $player[local.i].origin[2] > 0 && local.knife.origin[2] - $player[local.i].origin[2] <= local.playerheight)
    		{
    			if(isalive $player[local.i] && $player[local.i] != self)
    			{
    				if($player[local.i].dmteam != self.dmteam || (getcvar("g_gametype") == "1")) { killent $player[local.i].entnum } // "$player[local.i] kill" does not work if the player just respawned.
    				local.knife droptofloor												 // kill players regardless of teams if playing Free-for-All gametype.
    				
    				local.knife.angles = ( 0 local.knife.angles[1] local.knife.angles[2] ) // if a player was killed, droptofloor the knife and make knife's angles horizontal.
    				local.touchedplayer = 1
    				local.iold = local.i
    			}
    		}
    
    	}
    	if(local.touchedplayer != 1 && local.knife.flewlong != 1) 
    	{							// if player throws knife upwards, knife's origin lowers a few units in height so it's not inside the wall
    		local.height = local.fwd_vec[2] * -20		// if player throws knife downwards, knife's origin raises a few units in height.
    		local.knife.angles = local.anglesold 		// if knife stuck to a wall or object, make sure the knife's sharp end is always facing into the wall.
    	}
    	if(local.touchedplayer != 1 && local.knife.flewlong == 1) 
    	{	
    		local.height = local.fwd_vec[2] * 20		     // invert height adjustment, since anglesold is reversed.		
    		local.knife.angles = local.anglesold + ( 180 180 0 ) // if knife flew for a while and gravity brought it down, reverse anglesold so sharp end is facing the ground again.
    		if(local.fwd_vec[2] <= 0.06) { local.knife.angles = local.knife.angles + ( 0 180 0 ) } // undo reversal if player was looking horizontally.
    	}
    
    	if(local.fwd_vec[2] < 0) { local.fwd_vec[2] = local.fwd_vec[2] * -1 } // absolute-value.
    	if(local.fwd_vec[2] <= 0.06) { local.knife.angles = ( 0 local.knife.angles[1] local.knife.angles[2] ) + ( 0 180 0 ) } // if player's angles were almost horizontal, then keep the knife's angles horizontal.
    	if(local.fwd_vec[2] > 0.06) { local.knife.origin = local.knife.origin + ( 0 0 local.height ) }			      // otherwise, make the height adjustment as needed.
    
    	local.knife.rotate = 0
    	waitframe // wait for droptofloor to finish
    
    	if(local.touchedplayer == 1) 
    	{
    		if(local.fwd_vec[2] > 0.06) { local.knife.angles = local.knife.angles + ( 0 180 0 ) }  // if a player was touched, rotate the knife 180 degrees (sharp end faces forward), only if not looking horizontally.
    		local.knife.origin = $player[local.iold].origin
    	}
    
    	thread main local.name local.knife.origin local.knife.angles 1 1
    	local.knife remove	
    end
    
    rotate:
    
    	local.rotatespeed = randomint(50) + 80 // randomize rotation speed. min of 80, max of 130.
    	while(self.rotate == 1)
    	{
    		self.angles = (self.angles + ( local.rotatespeed 0 0 ))
    		waitframe
    	}
    end
    
    flytimer:
    
    	for(local.c = 0; self != NULL && local.c <= 5.5; local.c++) // 0.55 seconds estimated time until knife begins falling (downward trajectory) again due to gravity.
    	{
    		self.flewlong = 0	
    		wait 0.1	
    	}
    	if(self != NULL) { self.flewlong = 1 }
    end
    
    resettimer local.name local.light:	
    
    	for(local.c = 0; local.c <= (level.knife_resettime * 10); local.c++) 
    	{
    		if(self == NULL) { end }		   // if knife was picked up, end.
    		if(level.change_team_score == 1) { break } // for cyber attack / search & destroy mod, immediately reset all knives (not including those still held by living players).
    		wait 0.1
    	}
    	self.origin = ( level.knife_origin[local.name][0] level.knife_origin[local.name][1] level.knife_origin[local.name][2] ) // reset back to map-initial origins/angles for the knife.
    	self.angles = ( level.knife_angles[local.name][0] level.knife_angles[local.name][1] level.knife_angles[local.name][2] )
    	if(local.light != 1) { self light 0 0 0 0 }
    end

  7. #7

    Default

    Thank you, I know that the Ruckus Lamron throwing knife is a modded grenade added to the loadout as an "add item" in the grenade.tiks. Ive also seen it added in the state files "raise" i believe,
    But I add them to players loadout in sorridstrokers "weapon" player state mod simply with this -

    Code:
    local.knife = int(getcvar use_knife)
    
    	waitframe   //added
    
    if(local.knife != 0)
    	{
        	self give "models/weapons/throwing_knife.tik"
    	self ammo knife local.knife
    	}
    If i do the same thing with screwdriver it does not appear in the inventory

  8. #8

    Default

    This .pk3 shouldn't have any Windows Defender virus issues when opening the throwingknife.scr file. Not sure why, but my Defender was flagging my own .scr file as a virus and I couldn't open it in Notepad.

    Only way to fix that is to go to Windows Security --> Virus & Threat Protection --> Click "Manage settings" under Virus & threat protection settings --> Turn off "Real-time Protection. Now you can open .scr files without Defender flagging some of them as viruses (still not sure why that happens).
    Attached Files Attached Files

  9. #9

    Default

    I guess weapons need more than just a tik to appear in the inventory? is it an animation holding the weapon?

  10. #10

    Default

    The screwdriver.tik would need to have most of the extra code lines that a weapon.tik has, including classname weapon, name, weapontype, rank, meansofdeath, startammo, firedelay, firetype, movementspeed, etc.

    I haven't gotten much success with that. But if you want to spawn with knives in your inventory, you would have to run this in a $player.size for-loop after each time a player dies and respawns:
    Code:
    give_everyone_knives: // run after level waittill spawn
    
    	while(1)
    	{
    		for(local.c = 0; local.c <= $player.size; local.c++)
    		{
    			if(($player[local.c].knivesheld == NIL || $player[local.c].knivesheld < 1) && !isalive $player[local.c] && $player[local.c] != "spectator")
    			{
    				$player[local.c] thread spawn_with_knives
    			}
    
    		}
    		waitframe
    	}
    end
    
    spawn_with_knives:
    
    	self.knivesheld = 1 // or spawn with 2 or 3.
    	
    	while(!isalive self && $player[local.c] != "spectator") { waitframe }
    
    	self thread give_knife // from throwingknife.scr
    end
    Leave "give_knife" parameters NIL if you want the thrown/dropped knives to disappear completely after 45 seconds, might cause a few console errors, but no spam).
    Last edited by Searingwolfe; March 6th, 2023 at 10:20 PM. Reason: code

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •